diff options
| author | Craig Jennings <c@cjennings.net> | 2026-02-14 13:14:40 -0600 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-02-14 13:14:40 -0600 |
| commit | 82f10cc8258f17fbc42ed54b586385bfdf3f2091 (patch) | |
| tree | 4e10ac10a4a664843b90cbc4220749c06a39c881 | |
| parent | 176ea668cdd83beddd54a24334a8a9db3cc87dfb (diff) | |
Decouple task tracking from V2MOM strategic framework. Archive full
V2MOM history to v2mom.org, replace todo.org with flat task list under
Emacs Open Work / Emacs Resolved headings. Merge duplicate tasks
(org-noter, buttercup, localrepo, lorem-optimum). 29 open tasks, no
method grouping.
| -rw-r--r-- | todo.org | 1519 | ||||
| -rw-r--r-- | v2mom.org | 1671 |
2 files changed, 1780 insertions, 1410 deletions
@@ -1,35 +1,57 @@ -#+TITLE: Emacs Config V2MOM and Tasks +#+TITLE: Emacs Config Tasks #+AUTHOR: Craig Jennings -#+DATE: 2025-10-31 -#+FILETAGS: :v2mom:active: -* Instructions +* Emacs Open Work -This inbox contains ONLY tasks that serve the V2MOM vision. Before adding any task here, ask: -1. Does it serve the Vision? -2. Does it align with the Values? -3. Is it addressed in the Methods? -4. Does it overcome an Obstacle? -5. Does it improve a Metric? +** VERIFY [#B] Continue org-noter custom workflow implementation (IN PROGRESS) -If the answer is "no" to all five → DON'T ADD IT. +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. -V2MOM is located at: [[file:docs/emacs-config-v2mom.org][emacs-config-v2mom.org]] -Research/ideas that don't serve vision: [[file:docs/someday-maybe.org][someday-maybe.org]] +**Last worked on:** 2025-11-21 +**Current status:** Implementation complete but has bugs, needs testing -* Method 1: Make Using Emacs Frictionless [16/24] -** VERIFY [#B] Fix org-noter (reading/annotation workflow currently "so painful") +**Known Issues to Fix:** -High priority - daily pain point. +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 -** VERIFY [#B] Fix mail attachment workflow (currently awkward) +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 -Daily workflow improvement. +**Testing Needed:** -** DONE [#B] Optimize org-agenda performance using built-in profiler +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 -THE BOTTLENECK. Currently 30+ seconds, target < 5 seconds. -Use M-x profiler-start before Method 3 debug-profiling.el is built. +**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 + +** VERIFY [#B] Fix mail attachment workflow (currently awkward) + +Daily workflow improvement. ** TODO [#B] Optimize org-capture target building performance @@ -46,830 +68,67 @@ Changes in progress (modules/auth-config.el): - Use external pinentry (pinentry-dmenu) in GUI - Requires env-terminal-p from host-environment module -** DONE [#C] Verify format-buffer hands off to shfmt in shell scripts - -Need to verify that the format-buffer command correctly delegates to shfmt when -formatting shell scripts. May not be configured or may use wrong formatter. - -**Problem:** -- Unknown if format-buffer works in shell-script-mode -- May not be using shfmt (should use shfmt for shell scripts) -- May be using a different formatter (or no formatter) -- Need to verify configuration and test manually - -**Investigation:** -1. Find format-buffer implementation: - - Search for defun format-buffer in modules/ - - Check if it's in prog-general.el or separate module - - Review how it selects formatters per mode -2. Check shfmt configuration: - - Is shfmt installed? `which shfmt` - - Is shfmt configured for shell-script-mode? - - What are the shfmt command-line arguments? -3. Test manually: - - Create test shell script with bad formatting - - Run format-buffer command - - Verify it uses shfmt (not something else) - - Check formatted output is correct - -**Expected Behavior:** -1. In shell-script-mode buffer -2. Run format-buffer (or whatever the command is) -3. Should invoke shfmt to format the buffer -4. Output should be properly formatted shell code -5. Should preserve shebang and script functionality - -**Possible Issues:** - -A. **shfmt not installed** - - Check: `pacman -Q shfmt` or `which shfmt` - - Install if missing: `sudo pacman -S shfmt` - -B. **format-buffer not configured for shell** - - May only work for elisp/python/etc. - - Need to add shell-script-mode configuration - - Need to specify shfmt command - -C. **Wrong formatter used** - - May be using bashfmt, beautysh, or other tool - - Should specifically use shfmt (preferred) - -D. **format-buffer doesn't exist** - - May be using different command name - - Check for format-all, apheleia, or custom function - -**Manual Test:** -Create test file: -```bash -#!/bin/bash -# Poorly formatted script -if [ -f "test.txt" ];then -echo "found" -else - echo "not found" -fi -for i in 1 2 3;do echo $i;done -``` - -Expected after shfmt: -```bash -#!/bin/bash -# Poorly formatted script -if [ -f "test.txt" ]; then - echo "found" -else - echo "not found" -fi -for i in 1 2 3; do - echo $i -done -``` - -**Related Commands to Check:** -- format-buffer -- format-all-buffer -- apheleia-format-buffer -- Custom cj/format-buffer - -**Related Files:** -- modules/prog-general.el (likely location of format-buffer) -- modules/prog-shell.el (shell-specific config) -- Check for apheleia or format-all package config - -**Related Docs:** -- shfmt documentation: https://github.com/mvdan/sh -- format-all or apheleia package docs (whichever is used) -- V2MOM Method 1: Frictionless (formatting should just work) - -**Success Criteria:** -- format-buffer (or equivalent) command exists -- Works in shell-script-mode buffers -- Uses shfmt as the formatter -- Produces correctly formatted shell code -- Doesn't break script functionality -- Documented what command to use and how it works - -**If It Doesn't Work:** -1. Install shfmt: `sudo pacman -S shfmt` -2. Configure formatter (apheleia or format-all): - ```elisp - ;; Example configuration - (add-to-list 'apheleia-formatters - '(shfmt . ("shfmt" "-i" "2" "-ci"))) - (add-to-list 'apheleia-mode-alist - '(shell-script-mode . shfmt)) - ``` -3. Test again -4. Document in prog-shell.el - -**Note:** -Priority [#C] because formatting is nice-to-have. Can format manually with shfmt -if needed. Low priority but good for maintaining code quality in shell scripts. - -Normal case: File with #!/bin/bash at start should get +x permission." - (let ((test-file (make-temp-file "test-script-" nil ".sh"))) - (unwind-protect - (progn - ;; Write shebang to file - (with-temp-file test-file - (insert "#!/bin/bash\necho hello\n")) - ;; Remove execute permission - (set-file-modes test-file #o644) - (should-not (file-executable-p test-file)) - ;; Open file and trigger function - (with-current-buffer (find-file-noselect test-file) - (cj/make-script-executable) - (kill-buffer)) - ;; Verify file is now executable - (should (file-executable-p test-file))) - (delete-file test-file)))) -``` - -**Related Files:** -- modules/prog-shell.el:158-167 (function to test) -- tests/test-prog-shell-make-script-executable.el (NEW - create this) -- ai-prompts/quality-engineer.org (testing guidance) - -**Related Docs:** -- quality-engineer.org: File system testing best practices -- Recent test examples: test-custom-buffer-file-*.el (file operations) -- Emacs manual: File permissions and file-modes function - -**Success Criteria:** -- Comprehensive test file covering all normal/boundary/error cases -- All tests pass on Linux -- Tests properly clean up temp files -- Tests verify actual file permission changes -- Tests verify message output -- No false positives (making non-script files executable) -- No false negatives (missing files that should be executable) -- Tests document expected behavior (serve as specification) - -**Estimated Tests:** -- 6-8 normal cases (different shebangs) -- 8-10 boundary cases (edge conditions) -- 5-6 error cases (failure handling) -- Total: ~20-25 tests - -**Note:** -Priority [#B] because this function runs on every save in shell-script-mode and -modifying file permissions incorrectly could cause security issues or workflow -problems. Needs testing before any refactoring or changes. - ** VERIFY [#C] Fix EMMS keybinding inconsistency with other buffers 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. -** DONE [#D] Frequently used org-mode keybindings under C-; o - -Add quick access keybindings for common org commands (org-table, org-reveal, etc.) under C-; o. -Makes org-mode operations more frictionless. -Moved from inbox 2025-11-07. - -** DONE [#A] Music player is broken - mpd/mopidy need replacement -CLOSED: [2025-11-16 Sun 18:35] SCHEDULED: <2025-11-15 Fri> - -music-config.el integration with mpd and mopidy is broken. Need to migrate to -a different music player solution. Investigate alternatives: -- emms with VLC/mpv backend -- bongo player -- Simple mpv integration -- Other lightweight music player packages - -** DONE [#A] Fix recording workflow - phone call audio not captured (44 dB volume loss) -CLOSED: [2025-11-14 Thu] - -✅ **Fixed by replacing amerge+pan with amix FFmpeg filter** - -**Problem:** -On recorded calls, only one side was captured (user's microphone), not the other person's voice. -Phone call audio was too quiet to transcribe (44 dB volume loss). - -**Root Cause:** -FFmpeg's `amerge+pan` filter combination caused massive volume loss when mixing microphone -and system monitor inputs. The `pan` filter reduced volume by 50% and `amerge` had issues -with PulseAudio/PipeWire compatibility. - -**Solution:** -Replaced `amerge=inputs=2[merged];[merged]pan=mono|c0=0.5*c0+0.5*c1` with `amix=inputs=2:duration=longest` -filter. The `amix` filter properly mixes inputs without volume loss. - -**Changes Made:** -- Changed FFmpeg filter from `amerge+pan` to `amix` (modules/video-audio-recording.el:513) -- Increased default system volume from 0.5 to 2.0 (modules/video-audio-recording.el:76) -- Added diagnostic tool `C-; r w` to show active audio playback -- Created integration test with real voice recording -- Fixed batch mode compatibility for tests - -**Results:** -- Volume improved from -66.2 dB to -21.5 dB (44 dB improvement) -- Test transcription: 100% accurate ("Can you hear me? Testing, one, two, three.") -- Phone calls now capture both sides correctly - -**Testing:** -Automated integration test verifies monitor capture works with perfect transcription. -** DONE [#A] Fix Google Calendar password prompts every 15 minutes -CLOSED: [2025-11-11 Mon] - -✅ **Fixed oauth2-auto caching bug** - -**Root Cause:** -oauth2-auto.el version 20250624.1919 had a bug on line 206 that completely -disabled its internal token cache with `or nil`. This forced every org-gcal -sync to decrypt oauth2-auto.plist from disk, triggering GPG passphrase prompts -every ~15 minutes. - -**The Bug:** -```elisp -;; Line 201-213 in oauth2-auto.el (BEFORE fix) -(defun oauth2-auto--plstore-read (username provider) - "Read the data for USERNAME and PROVIDER from the cache, else from plstore." - (let ((id (oauth2-auto--compute-id username provider))) - ; Assume cache is invalidated. FIXME - (or nil ;(gethash id oauth2-auto--plstore-cache) ;; BUG: cache disabled! - (let ((plstore (plstore-open oauth2-auto-plstore))) - ...)))) -``` - -**The Fix:** -Enabled the internal hash-table cache by removing `or nil`: -```elisp -;; Line 201-213 in oauth2-auto.el (AFTER fix) -(defun oauth2-auto--plstore-read (username provider) - "Read the data for USERNAME and PROVIDER from the cache, else from plstore." - (let ((id (oauth2-auto--compute-id username provider))) - ;; FIXED: Enable cache to prevent repeated GPG passphrase prompts - (or (gethash id oauth2-auto--plstore-cache) ;; Cache now works! - (let ((plstore (plstore-open oauth2-auto-plstore))) - ...)))) -``` - -**What Changed:** -1. Modified elpa/oauth2-auto-20250624.1919/oauth2-auto.el:201-213 -2. Removed `or nil` that disabled cache -3. Added `cj/clear-oauth2-auto-cache` helper function in auth-config.el -4. Documented fix in auth-config.el commentary (lines 16-22) - -**Result:** -- GPG passphrase prompted ONCE per Emacs session (when first accessing tokens) -- oauth2-auto now caches tokens in memory (oauth2-auto--plstore-cache) -- No more interruptions during org-gcal auto-sync every 30 minutes -- Workflow is now frictionless as intended - -**Testing:** -After restart: -1. First org-gcal sync prompts for passphrase (expected) -2. Subsequent syncs use cached tokens (no prompts) -3. Cache persists until Emacs closes - -**Files Modified:** -- elpa/oauth2-auto-20250624.1919/oauth2-auto.el (cache fix) -- modules/auth-config.el (documentation + helper function) - -Priority [#A] because password prompts every 15 minutes violated "Frictionless" value. -Fixed 2025-11-11. - -** DONE [#A] Fix audio recording device selection - still broken with Jabra headset -CLOSED: [2025-11-11 Mon] - -✅ **Fixed audio recording bug + improved UX** - -**Root Cause:** -Auto-detection only looked for `analog.*stereo` which matched laptop audio but never -Bluetooth/Jabra devices. User was always recording from laptop mic (silent when using Jabra). - -**What Was Fixed:** - -1. **Removed broken auto-detection** (lines 58-77) - - Old code only detected built-in laptop audio - - Never detected Bluetooth/USB/Jabra devices - - This is why recordings were silent - -2. **Force explicit device selection on first use** - - C-; r a now prompts for device setup if not configured - - Suggests quick setup (C-; r c) by default - - Device selection persists across Emacs sessions - -3. **Simplified keybindings to toggle start/stop** - - C-; r a → Toggle audio recording (start/stop) - - C-; r v → Toggle video recording (start/stop) - - Removed separate stop keybindings (A, V) - - One key to remember, press again to stop! - -4. **Added device testing functions** (lines 233-314) - - C-; r t b → Test both mic + monitor (guided, RECOMMENDED) - - C-; r t m → Test microphone only (5 sec) - - C-; r t s → Test system audio/monitor only (5 sec) - - Catch hardware issues before important recordings - -5. **Added modeline recording indicator** - - 🔴Audio appears when recording audio - - 🔴Video appears when recording video - - 🔴A+V appears when recording both - - Indicator and toggle always in sync (same process variables) - - Process sentinel auto-clears on crash/kill - -**New Workflow:** -``` -Press C-; r a - ↓ -First time? → Device setup → Choose Jabra → Start (🔴Audio appears) - ↓ -Already configured? → Start immediately (🔴Audio appears) - ↓ -Press C-; r a again → Stop (🔴 disappears) -``` - -**Files Modified:** -- modules/video-audio-recording.el (removed auto-detect, added tests, toggle functions, modeline indicator) -- modules/modeline-config.el (added 🔴 recording indicator to right side) - -**Testing:** -After Emacs restart: -1. Press C-; r a -2. Choose "Bluetooth Headset" (Jabra) -3. See 🔴Audio in modeline -4. Speak and play audio -5. Press C-; r a to stop -6. Verify recording has audio - -Priority [#A] because blocked daily recording and transcription workflows. -Fixed 2025-11-11. - -** DONE [#A] Remove network check from startup (saves 1+ seconds) -CLOSED: [2025-10-31 Fri] - -✅ Deleted blocking ping check. Startup improved from 6.2s to 5.4s. -Now uses package priorities: .localrepo (200) > online repos (25). - -** DONE [#A] Fix cj/goto-git-gutter-diff-hunks (missing function causing errors) -CLOSED: [2025-11-03 Sun] - -✅ Implemented missing function in modules/vc-config.el -- Added `cj/goto-git-gutter-diff-hunks` function (lines 118-124) -- Uses consult-line to search for diff markers (^[+\-]) -- Enables interactive jumping to any changed line via C-; v d -- Function properly documented with docstring -- No linting issues, compiles cleanly - -Quick win completed - 5 minutes actual time. - -** DONE [#A] Fix chime-check throw with no catch block -CLOSED: [2025-11-01 Fri] - -Error: "(no-catch --cl-block-chime-check-- nil)" -Chime was throwing to a catch block that doesn't exist. -Location: chime package - chime-check() function at line 1540 -Fix: Changed defun to cl-defun to provide implicit catch block for cl-return-from. - -Fixed in ~/code/chime.el/chime.el:1540 - -Added regression test: test-integration-startup-early-return-on-validation-failure -Created Makefile with test targets (unit, integration, all, by-file, by-name) -Updated README.org with Development/Testing section - -All integration tests pass (5/5) ✅ - -** DONE [#A] Implement cj/diff-buffer-with-file (compare buffer with saved version) -CLOSED: [2025-10-31 Fri] - -Bound to C-; b D. Weekly need satisfied. - -** DONE [#A] Add comprehensive test coverage for video-audio-recording module -CLOSED: [2025-11-03 Sun] - -✅ Created comprehensive test suite following quality-engineer.org standards: -- 9 test files (8 unit + 1 integration) -- 83 test cases with 100% pass rate -- Test categories: Normal, Boundary, Error cases -- 6 test fixtures for reproducible testing -- Mocking strategy using cl-letf -- Integration test validates complete parse→group→friendly-names workflow -- Tests document bugs in legacy detect functions -- Critical validation: Bluetooth MAC normalization across component boundaries - -✅ Refactored code for testability: -- Extracted `cj/recording--parse-pactl-output` internal parser -- Separated I/O from business logic - -✅ Fixed all linting warnings (checkdoc): -- 6 spacing/grammar issues resolved -- `make lint` now passes cleanly - -✅ All changes committed and pushed to all remotes (origin + github) - -Commits: -- 0a69c58: test: Add comprehensive test suite for video-audio-recording module -- b086539: style: Fix checkdoc warnings in video-audio-recording.el - -*** DONE [#C] Add device testing command cj/recording-test-devices -CLOSED: [2026-02-06 Thu] -Records 3 seconds of audio. -Plays it back. -Confirms devices work before real recording. - -*** CANCELLED [#C] Add recording status display (optional via flag, default off) -CLOSED: [2026-02-14 Sat] -Emoji modeline icon is sufficient. - -*** CANCELLED [#C] Add recording presets -CLOSED: [2026-02-14 Sat] -Only used for meetings; emoji icon is good-enough reminder. Gold-plating. - -*** CANCELLED [#C] Build recording history buffer -CLOSED: [2026-02-14 Sat] -Opening recordings in dirvish is sufficient. +** TODO [#C] Add post-processing hooks (recording) -*** TODO [#C] Add post-processing hooks Auto-compress after recording. Move to cloud sync directory. Generate transcript (once transcription workflow exists). -** DONE [#A] Delay in modeline lines and columns update -CLOSED: [2025-11-08 Fri] - -✅ Fixed modeline position lag by replacing expensive function calls with cached values. - -**Problem:** -- Line/column numbers lagged behind cursor movement -- Used `line-number-at-pos` which counts from buffer start on every update -- Performance degraded in large files - -**Solution:** -- Replaced with built-in format specifiers `%l` and `%c` (modeline-config.el:81) -- These use cached values maintained by line-number-mode and column-number-mode -- Explicitly enabled line-number-mode in ui-config.el:53 -- Zero performance overhead - cached values update instantly - -**Result:** -- Modeline position now updates instantly with cursor movement -- No lag, even in large files -- Maintains same "L:line C:col" format - -** DONE [#B] Toggle org-appear on/off -CLOSED: [2025-11-16 Sat] - -✅ **Implemented toggle function with C-c C-a keybinding** - -Created `cj/org-appear-toggle` function that toggles org-appear-mode on/off in -current org buffer. Default is OFF (cleaner for reading), can be toggled ON when -editing links, then toggled OFF again. - -**Implementation:** -- Removed :disabled flag and :hook (default: OFF) -- Created cj/org-appear-toggle function with clear user feedback -- Bound to C-c C-a in org-mode-map (unbound, no conflicts) -- Tested: toggles correctly, all tests pass - -**Usage:** -- C-c C-a: Toggle on/off -- Default: OFF (links and emphasis markers stay hidden) -- Messages show current state clearly - -Moved from inbox 2025-11-07. Completed 2025-11-16. - -** DONE [#B] Consider implementing cron download of Google Calendar to replace org-gcal -CLOSED: [2025-11-16 Sat] - -Replaced problematic org-gcal OAuth workflow with calendar-sync.el module. -Implemented pure Elisp .ics parser with timer-based sync (no cron needed). - -**Current Problem:** -From TODO at line 22-66: -- org-gcal prompts for password every ~15 minutes -- OAuth token refresh bypasses cache -- plstore symmetric encryption cache issues -- Interrupts workflow constantly -- Makes calendar sync painful instead of seamless - -**Proposed Solution:** -Instead of OAuth-based sync (org-gcal), use Google Calendar's public iCalendar URLs: -1. Download .ics file via cron (every 15-30 minutes) -2. Parse .ics file into org-mode format -3. Update org-agenda files automatically -4. No OAuth, no passwords, no interruptions - -**Benefits:** -- ✓ No password prompts (public calendar URL or one-time API key) -- ✓ No OAuth token refresh issues -- ✓ Runs in background (cron), never interrupts work -- ✓ Simpler architecture (download → parse → update) -- ✓ Can work offline (reads last downloaded .ics) -- ✓ More reliable (fewer moving parts) -- ✓ No plstore symmetric encryption issues - -**Drawbacks:** -- ✗ Read-only (can't create/update events from Emacs) -- ✗ Need to manually get calendar iCal URL -- ✗ Requires cron setup (one-time configuration) -- ✗ May have sync delay (up to cron interval) - -**Investigation:** - -1. **Get Google Calendar iCal URL:** - - Open Google Calendar settings - - Find "Integrate calendar" section - - Copy secret iCal address (https://calendar.google.com/calendar/ical/...) - - Store in auth-source (encrypted) - -2. **Test iCal download:** - ```bash - curl -o calendar.ics "https://calendar.google.com/calendar/ical/.../basic.ics" - ``` - - Verify it downloads - - Check .ics format - - Confirm events are present - -3. **Research iCal parsing:** - - Does Emacs have built-in iCal parser? (icalendar.el) - - Check icalendar-import-file function - - Test parsing downloaded .ics file - - Verify it creates org entries - -4. **Design cron workflow:** - ```bash - # Every 15 minutes - */15 * * * * curl -s "$(cat ~/.calendar-url)" -o ~/calendars/gcal.ics - ``` - - Downloads silently in background - - Emacs watches file for changes (file-notify) - - Auto-reimport when changed - -**Possible Implementations:** - -A. **Full replacement (recommended):** - - Remove org-gcal entirely - - Use cron + icalendar.el - - Read-only calendar view in org-agenda - - Create events directly in Google Calendar web UI - -B. **Hybrid approach:** - - Keep org-gcal for writing events - - Use cron download for reading events - - Disable org-gcal auto-sync (no password prompts) - - Manually trigger org-gcal only when creating events - -C. **Enhanced cron:** - - Cron downloads .ics - - Emacs function parses and updates org files - - Add file-notify watcher for auto-update - - Optional: Convert two-way with CalDAV later - -**Implementation Sketch:** -```elisp -(defun cj/calendar-import-gcal () - "Import Google Calendar from downloaded .ics file." - (interactive) - (let ((ics-file "~/calendars/gcal.ics") - (org-file "~/org/calendar.org")) - (when (file-exists-p ics-file) - (icalendar-import-file ics-file org-file) - (message "Imported calendar from %s" ics-file)))) - -;; Auto-import when .ics file changes -(file-notify-add-watch - "~/calendars/gcal.ics" - '(change) - (lambda (event) (cj/calendar-import-gcal))) -``` - -**Related Files:** -- modules/org-gcal-config.el (current problematic implementation) -- Emacs built-in: icalendar.el (iCal parsing) -- System: crontab -e (download schedule) -- ~/.authinfo.gpg (store calendar URL securely) - -**Related Docs:** -- Current problem: TODO line 22-66 (password prompts every 15 min) -- icalendar.el manual: C-h f icalendar-import-file -- Google Calendar iCal format documentation -- V2MOM Method 1: Frictionless (no interruptions!) - -**Success Criteria:** -- Calendar events appear in org-agenda -- No password prompts during work -- Updates automatically in background (cron) -- Can work offline with last sync -- Setup is one-time configuration -- Simpler than current org-gcal setup - -**Testing Plan:** -1. Get iCal URL from Google Calendar -2. Test download: `curl URL -o test.ics` -3. Test import: `M-x icalendar-import-file` -4. Verify org entries created correctly -5. Set up cron job -6. Wait for auto-update -7. Confirm events in org-agenda -8. Disable org-gcal auto-sync -9. Monitor for 1 week (no password prompts?) - -**Decision Point:** -This is a significant architectural change. Need to: -1. Test proof-of-concept first (manual download + import) -2. Evaluate if read-only is acceptable -3. Compare to fixing OAuth password prompts -4. Consider hybrid approach if two-way sync needed - -**Note:** -Priority [#B] because this could eliminate the #1 daily irritant (password prompts -every 15 minutes). If proof-of-concept works, this is higher value than fixing -OAuth issues. Simpler architecture = fewer problems. - -** DONE [#B] Add time-zones package for quick timezone lookups -CLOSED: [2025-11-14 Fri 02:42] - -IRRITANT: Need to frequently check time differences between cities (London, Lisbon, -New Orleans, San Francisco) for meetings and coordination. Currently requires stopping -work, searching web/using external app, context switching back. - -**Pain Point:** -Multiple times per week, need to know "what time is it in London right now?" or -"if I schedule this for 2pm my time, what time is that in Lisbon?" This breaks -flow and requires leaving Emacs. - -**Solution:** -Use time-zones package: https://github.com/xenodium/time-zones - -Built-in world-clock exists (M-x world-clock) but lacks two critical features: -1. Can't interactively add cities with fuzzy search -2. Can't shift time forward/backward to check future times - -time-zones package adds both features - making timezone checks instant and frictionless. - -**Expected Workflow:** -- M-x time-zones (or keybinding C-; T z or similar) -- Interactively add/remove cities with completion -- Shift time forward/backward to check meeting times -- Stay in Emacs, maintain flow - -**Files:** -- Create new module: modules/time-zones-config.el -- Add require to init.el in appropriate section -- Configure default cities list (London, Lisbon, New Orleans, San Francisco) -- Add keybinding (suggest C-; T z for time zones) - -**V2MOM Alignment:** -Method 1 - Frictionless: Eliminates context switch for common timezone queries. -Intuitive value: Quick keybinding for frequent operation. - -** DONE [#B] Fix go-ts-mode-map keybinding error (void-variable) -CLOSED: [2025-11-03 Sun] - -Error: "Debugger entered--Lisp error: (void-variable go-ts-mode-map)" -Location: modules/prog-go.el - trying to bind keys before mode loads. - -✅ Already fixed in commit 196b289 (Nov 2, 2025) -- Moved keybinding from `:bind (:map go-ts-mode-map ...)` to hook function -- Keybinding now set in `cj/go-mode-keybindings` called via `:hook` -- Function executes after mode loads, ensuring keymap exists -- Today's cleanup: Removed unused forward declarations (lines 34-35) - -Fix was: Wrap keybinding in hook function instead of :bind clause. -Result: No more void-variable error, keybinding works correctly. - -** DONE [#B] Fix video/audio recording module (use constantly, just broke) -CLOSED: [2025-11-03 Sun] - -Main issue: No way to select audio devices when multiple are available. -Plugging in external audio interface broke recording - only captured input, not output. - -✅ COMPLETED - Module now has robust device detection and selection. - -*** DONE [#A] Add diagnostic command cj/recording-list-devices -CLOSED: [2025-11-03 Sun] - -✅ Created `cj/recording-list-devices` command (C-; r d) -Shows ALL available PulseAudio/PipeWire sources with drivers and states. -Displays current configuration. -Helps debug why auto-detection fails. - -*** DONE [#A] Add device selection UI -CLOSED: [2025-11-03 Sun] - -✅ Created TWO selection workflows: -1. `cj/recording-select-devices` (C-; r s) - Full manual control - - Select mic and system audio separately - - Interactive completion with device states -2. `cj/recording-quick-setup-for-calls` (C-; r c) - Quick call setup - - Smart device pairing (groups mic + monitor by hardware) - - One selection for both mic and system audio - - Handles Bluetooth MAC normalization - -Devices cached in variables for future recordings. -Can switch devices without restarting Emacs. - -*** DONE [#B] Improve error messages -CLOSED: [2025-11-03 Sun] - -✅ Error messages now include: -- Guidance to run `cj/recording-select-devices` -- Clear indication when auto-detection fails -- User-friendly prompts for manual selection +** TODO [#B] Validate recording startup -*** DONE [#B] Make device detection more flexible -CLOSED: [2025-11-03 Sun] - -✅ Implemented multi-level fallback system: -1. Auto-detect using pactl output parsing -2. Prompt user to select manually if auto-detect fails -3. Error with helpful guidance if user declines - -✅ Smart device grouping in `cj/recording-group-devices-by-hardware`: -- Handles USB, PCI (built-in), and Bluetooth devices -- Normalizes Bluetooth MAC addresses (colons ↔ underscores) -- Assigns friendly names (e.g., "Built-in Laptop Audio", "Bluetooth Headset") -- Filters incomplete devices (must have both mic and monitor) - -✅ Supports both PulseAudio and PipeWire (both use pactl). - -*** TODO [#B] Validate recording startup Check process status after starting. Parse ffmpeg output for errors. Show actual ffmpeg command for debugging. -** DONE [#C] Fix grammar checker performance (currently disabled) -CLOSED: [2025-11-04 Mon] - -✅ **Installed and configured LanguageTool for comprehensive grammar checking** - -Replaced disabled grammar checker with on-demand LanguageTool integration: -- Installed LanguageTool 6.6-2 from Arch repos (222MB) -- Created wrapper script: scripts/languagetool-flycheck (Python 3) -- Integrated with flycheck for on-demand checking via C-; ? -- Removed proselint (redundant - LanguageTool catches more) -- No performance impact: only runs when explicitly invoked -- Installation instructions added to modules/flycheck-config.el commentary - -LanguageTool catches: -- Real grammar errors (subject-verb agreement, tense, etc.) -- Missing punctuation (commas, periods) -- Common mistakes (could of → could have) -- Style issues (redundant phrases, wordiness) - -Workflow: Open org/text/markdown file → press C-; ? → see errors in *Flycheck errors* buffer - -** DONE [#C] cj/flyspell-then-abbrev loses keybinding in scratch org-mode buffer -CLOSED: [2025-11-08 Fri] - -✅ Fixed keybinding issue in org-mode buffers. - -**Problem:** -1. Autoload cookies were just comments and never executed -2. Org-mode was overriding C-' with org-cycle-agenda-files - -**Solution:** -- Set keybindings directly when module loads (lines 239-240) -- Explicitly override org-mode's C-' after org loads (lines 244-245) -- Both C-' and C-c f now work correctly in all buffers including org-mode - -File modified: modules/flyspell-and-abbrev.el:235-251 - -* Method 2: Stop Problems Before They Appear [4/8] ** TODO [#B] Write Complete ERT Tests for This Config [0/31] + Unit and Integration Tests should be added as subtasks below, marked done when complete. *High-value test targets (no coverage, testable logic, daily use):* -*** TODO custom-case — pure case conversion functions (upper/lower/title) -*** TODO custom-datetime — date/timestamp insertion and formatting -*** TODO host-environment — platform detection (env-macos-p, env-wayland-p, etc.) -*** TODO hugo-config — draft toggle, slug generation, post template -*** TODO org-capture-config — template building (relates to capture perf optimization) -*** TODO modeline-config — custom segment construction -*** TODO external-open — file-type detection and external app dispatch -*** TODO reconcile-open-repos — dirty repo scanning logic -*** TODO media-utils — URL download/play logic -*** TODO org-config — org-mode utility functions -*** TODO org-export-config — export helper functions -*** TODO local-repository — package snapshot logic -*** TODO show-kill-ring — kill ring display logic -*** TODO system-commands — reboot/logout/system action functions -*** TODO config-utilities — debug helper functions +- [ ] custom-case — pure case conversion functions (upper/lower/title) +- [ ] custom-datetime — date/timestamp insertion and formatting +- [ ] host-environment — platform detection (env-macos-p, env-wayland-p, etc.) +- [ ] hugo-config — draft toggle, slug generation, post template +- [ ] org-capture-config — template building (relates to capture perf optimization) +- [ ] modeline-config — custom segment construction +- [ ] external-open — file-type detection and external app dispatch +- [ ] reconcile-open-repos — dirty repo scanning logic +- [ ] media-utils — URL download/play logic +- [ ] org-config — org-mode utility functions +- [ ] org-export-config — export helper functions +- [ ] local-repository — package snapshot logic +- [ ] show-kill-ring — kill ring display logic +- [ ] system-commands — reboot/logout/system action functions +- [ ] config-utilities — debug helper functions *Modules with partial coverage (expand existing tests):* -*** TODO org-agenda-config — caching/TTL logic untested (only build-list covered) -*** TODO org-contacts-config — expand beyond capture/parse -*** TODO prog-shell — expand beyond make-script-executable -*** TODO ui-config — expand beyond buffer-status/cursor-color -*** TODO org-refile-config — expand beyond build-targets -*** TODO org-webclipper — expand beyond process (only 1 test file) -*** TODO org-noter-config — expand beyond generate-notes/title-to-slug -*** TODO browser-config — expand beyond current single test file -*** TODO flycheck-config — expand beyond languagetool setup -*** TODO org-drill-config — expand beyond first-function/font-switching +- [ ] org-agenda-config — caching/TTL logic untested (only build-list covered) +- [ ] org-contacts-config — expand beyond capture/parse +- [ ] prog-shell — expand beyond make-script-executable +- [ ] ui-config — expand beyond buffer-status/cursor-color +- [ ] org-refile-config — expand beyond build-targets +- [ ] org-webclipper — expand beyond process (only 1 test file) +- [ ] org-noter-config — expand beyond generate-notes/title-to-slug +- [ ] browser-config — expand beyond current single test file +- [ ] flycheck-config — expand beyond languagetool setup +- [ ] org-drill-config — expand beyond first-function/font-switching *Lower priority (testable but less critical):* -*** TODO chrono-tools — timer/clock functions -*** TODO help-utils — search dispatch (arch-wiki, devdoc, tldr, wikipedia) -*** TODO dirvish-config — wallpaper setter, custom functions -*** TODO dwim-shell-config — shell command definitions -*** TODO elfeed-config — podcast/feed helper functions -*** TODO eww-config — browser helper functions +- [ ] chrono-tools — timer/clock functions +- [ ] help-utils — search dispatch (arch-wiki, devdoc, tldr, wikipedia) +- [ ] dirvish-config — wallpaper setter, custom functions +- [ ] dwim-shell-config — shell command definitions +- [ ] elfeed-config — podcast/feed helper functions +- [ ] eww-config — browser helper functions ** TODO [#B] Review all config and pull library functions into system-lib file @@ -908,31 +167,12 @@ This makes them: 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) - -**Related Files:** -- modules/system-lib.el (target file) -- modules/host-environment.el (likely source) -- modules/system-utils.el (likely source) -- modules/config-utilities.el (check for candidates) -- tests/test-system-lib-*.el (add tests for moved functions) - -**Related Docs:** -- Recent refactoring: Created system-lib.el with cj/executable-exists-p -- Testing guidance: ai-prompts/quality-engineer.org -- V2MOM Method 2: Stop Problems Before They Appear (better organization) - -**Success Criteria:** -- All generic system utilities consolidated in system-lib.el -- Each function has comprehensive test coverage -- No functionality broken (all tests pass) -- Documentation explains purpose and scope of system-lib.el -- Other modules properly require system-lib where needed +- 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 [#C] Migrate from Company to Corfu :PROPERTIES: @@ -945,351 +185,19 @@ Complete config already exists in someday-maybe.org. Just needs to be executed. Already using prescient with vertico. Extend to Corfu after migration. -** DONE [#B] Move cj/log-silently to system-lib -CLOSED: [2025-11-16 Sun 18:36] - -The `cj/log-silently` function is a generic utility for logging messages without -displaying them in the echo area. It should be moved to system-lib.el for better -organization and reusability across modules. - -**Current Problem:** -- cj/log-silently is likely defined in a specific module -- It's a generic logging utility that could be used by any module -- Not easily discoverable for reuse -- Doesn't follow the system-lib pattern we're establishing - -**What is cj/log-silently?** -This function logs messages to the *Messages* buffer without interrupting the user -by displaying them in the echo area (minibuffer). Useful for debugging and tracing -code execution without breaking user flow. - -**Task:** -1. **Find current location:** - ```bash - grep -rn "defun cj/log-silently" modules/ - ``` - -2. **Review implementation:** - - Check if it has dependencies on mode-specific functionality - - Verify it's truly generic (should be) - - Check for any callers that need updating - -3. **Move to system-lib.el:** - - Cut from current location - - Paste into system-lib.el - - Add appropriate commentary/docstring - - Ensure proper section organization - -4. **Update callers:** - - Find all uses: `grep -rn "cj/log-silently" modules/` - - Add `(require 'system-lib)` to any module that uses it - - Verify no circular dependencies - -5. **Write tests:** - Create `tests/test-system-lib-log-silently.el` with coverage for: - - Normal cases: logging simple messages - - Boundary cases: empty strings, very long messages, special characters - - Error cases: nil input, non-string input - - Verify output: check *Messages* buffer contains logged text - - Verify silence: ensure nothing appears in echo area - -**Expected Signature:** -```elisp -(defun cj/log-silently (format-string &rest args) - "Log a message to *Messages* buffer without displaying in echo area. -FORMAT-STRING and ARGS work like `message' but output is not shown to user." - (let ((inhibit-message t)) - (apply #'message format-string args))) -``` - -**Related Files:** -- modules/system-lib.el (destination) -- Current module where cj/log-silently lives (TBD - find it) -- All modules that call cj/log-silently (update requires) -- tests/test-system-lib-log-silently.el (NEW - create this) - -**Related Docs:** -- System-lib refactoring initiative (previous TODO) -- quality-engineer.org (testing guidance) -- Recent refactoring: moved cj/executable-exists-p to system-lib -- V2MOM Method 2: Stop Problems Before They Appear (better organization) - -**Success Criteria:** -- cj/log-silently moved to system-lib.el -- All callers updated with proper requires -- Comprehensive test coverage (normal/boundary/error cases) -- All existing tests still pass (no regressions) -- Function works identically to before -- Well-documented in system-lib.el - -**Testing:** -1. Run all tests before move (baseline) -2. Move function and update requires -3. Run all tests after move (verify no breakage) -4. Run new cj/log-silently tests (verify behavior) -5. Test in real usage (logging works, messages not shown) - -**Note:** -Priority [#B] because this is part of the larger system-lib consolidation effort -(separate TODO). Logging utilities are commonly used, so centralizing them improves -discoverability and encourages consistent logging patterns across the codebase. - -** DONE [#C] Switch to mood-line (actually: built custom modeline) -CLOSED: [2025-11-03 Sun] - -✅ **Built custom modeline (better than mood-line)** - -Went beyond mood-line and created a fully custom modeline using only built-in -Emacs functionality to avoid native-compilation issues. Features: - -**Architecture:** -- Named segment system using defvar-local (easy to reorder) -- Emacs 30 built-in right-alignment (mode-line-format-right-align) -- All segments marked as risky-local-variable for proper evaluation - -**Interactive Features:** -- Color-coded buffer names (green=writeable, red=read-only, gold=overwrite) -- VC branch with git symbol () and state-based coloring -- Mouse click handlers: buffer name (prev/next), branch (vc-diff), mode (describe-mode) -- Help-echo tooltips on all segments -- String truncation for narrow windows (< 100 chars wide) -- Active-window-only display for branch and misc-info (less clutter) - -**Layout:** -- Left: Major mode, buffer name, position (L:# C:#) -- Right: Git branch, chime notifications - -**Bug Fixes:** -- Disabled async native compilation (prevented "Selecting deleted buffer" errors) -- Fixed difftastic loading (:demand → :defer) -- Abstracted buffer status colors to user-constants.el - -Inspired by Prot's modeline design. See commit c0c4b17. - -** DONE [#C] Remove deprecated tree-sitter package (rely on treesit-auto) -CLOSED: [2025-11-03 Sun] - -✅ Removed deprecated tree-sitter package from modules/prog-general.el -- Deleted `(use-package tree-sitter)` on line 97 -- Now relies solely on Emacs 29+ built-in treesit with treesit-auto -- treesit-auto continues to manage tree-sitter grammars automatically -- No functionality lost, cleaner dependency tree - -** DONE [#C] Add org-appear (show emphasis markers only when point is on them) -CLOSED: [2025-11-03 Sun] - -✅ Added org-appear package to modules/org-config.el -- Shows emphasis markers (* / _) only when cursor is on them -- Also shows link markup and sub/superscripts when editing -- Changed org-fontify-emphasized-text from nil to t (line 75) -- Updated comment on line 71 to reference org-appear -- Cleaner editing experience while maintaining visual clarity - -* Method 3: Make *Fixing* Emacs Frictionless [0/9] -** DONE [#A] Write tests for cj/make-script-executable (suspected broken) -CLOSED: [2025-11-11 Tue] - -The `cj/make-script-executable` function automatically makes shell scripts executable -when they have a shebang, but has no test coverage. **Suspected to be broken/not working.** -This is a critical function that modifies file permissions and runs on every save. - -**Function Location:** -modules/prog-shell.el:158-167 - -**Why This Matters:** -1. Runs automatically on after-save-hook in shell-script-mode (high frequency) -2. Modifies file permissions (security-relevant) -3. If broken, scripts won't become executable automatically -4. No test coverage means bugs go undetected - -**Investigation First:** -1. Test manually: Create test.sh with `#!/bin/bash`, save, check if executable -2. Check if function is actually hooked to after-save-hook -3. Verify conditions in function logic are correct -4. Look for any error messages in *Messages* buffer - -**Then Write Tests:** -Following quality-engineer.org patterns: -- Normal cases: Various shebangs (bash, python, ruby, etc.) -- Boundary cases: Shebang with spaces, not at start, already executable -- Error cases: No file, read-only filesystem, permission errors - -**Estimated Work:** -- Manual testing: 15 minutes -- Writing comprehensive tests: 2-3 hours -- ~20-25 tests total - -**Success Criteria:** -- Confirm function works or identify bug -- Comprehensive test coverage -- Tests document expected behavior -- Can refactor safely with tests as safety net - -Priority [#B] because if broken, it's a daily workflow issue (scripts don't auto-execute). -Moved from inbox 2025-11-11. - -** DONE [#A] Fix difftastic integration - not showing semantic diffs (just unified diff) -CLOSED: [2025-11-11 Tue] - -Difftastic was marked as "integrated" but diffs in magit and custom-buffer-file.el look -identical to standard unified diffs. **Likely not actually using difftastic** - probably -falling back to git diff or missing a configuration switch. - -**Problem:** -Two places where difftastic should work but doesn't: -1. **Magit diffs** - Should show semantic diffs with D/S keybindings, but looks like unified diff -2. **Buffer diff** (custom-buffer-file.el) - cj/diff-buffer-with-file should use difftastic but looks like unified diff - -**Investigation:** -1. Check if difftastic binary actually gets called: - - Test: `difft --version` (verify binary exists) - - Test: `difft file1.el file2.el` manually to see what output looks like - - Should show syntax-aware, tree-based diff (very different from unified) - -2. Review vc-config.el difftastic setup (lines ~176-190): - - Is difftastic.el package loaded? (check with `M-x package-list-packages`) - - Are keybindings actually bound? (check magit-diff-mode-map) - - Is there a configuration switch we're missing? - -3. Check custom-buffer-file.el: - - Claims to use ediff (line 554-565), not difftastic - - Confusion: Is it supposed to use difftastic or ediff? - - If ediff, that's different tool (interactive split-screen, not semantic) - -**Possible Issues:** -A. difftastic.el not actually loaded (:defer preventing it) -B. Missing transient menu configuration for magit -C. Need to enable difftastic-mode explicitly -D. Keybindings shadowed by other bindings -E. ANSI color codes not rendering (looks wrong but is difftastic) - -**Expected Behavior:** -Difftastic output should look VERY different from unified diff: -- Tree-based syntax matching -- Side-by-side or structured format -- Language-aware (knows it's elisp/org/etc) -- Shows matched nodes, not just line changes - -**Next Steps:** -1. Run difft manually on two .el files to see expected output -2. Try calling difftastic functions directly: `M-x difftastic-magit-diff` -3. Check *Messages* for errors when using D/S in magit -4. Review difftastic.el documentation for required configuration - -**Related Files:** -- modules/vc-config.el (difftastic config) -- modules/custom-buffer-file.el (buffer diff - might be ediff, not difftastic?) -- Binary: /usr/bin/difft - -**Success Criteria:** -- Diffs in magit show obvious semantic/structural differences -- Output clearly different from unified diff -- Can visually identify it's difftastic (not git diff) -- Documented how to use and what to expect - -Priority [#B] because if not working, we're not getting the benefit of difftastic integration. -Moved from inbox 2025-11-11. - -** TODO [#B] Build debug-profiling.el module - -Reusable profiling infrastructure for any future performance work. -** TODO [#C] Evaluate Buttercup for integration tests -** TODO [#B] Add project-aware ERT test isolation when switching projects - -When switching between elisp projects (e.g., emacs.d to chime.el), 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.el -- 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 - -Priority [#B] because affects daily workflow when working on multiple elisp projects. -Moved from inbox 2025-11-11. - -** DONE [#B] Remove ANSI color codes from Makefile - breaks test output readability -CLOSED: [2025-11-11 Tue] - -ANSI color codes render incorrectly in some terminals, making test output unreadable. -Can see it's colored red, but can't read what the actual error message says due to -escape code littering throughout the text. Blocks debugging. - -**Problem:** -- Makefile uses variables like `COLOR_GREEN`, `COLOR_RED`, `COLOR_BLUE` -- These insert ANSI escape codes like `\033[0;32m` into output -- Makes output harder to read, especially in logs or when piped -- Color codes don't work well in all terminals -- Unnecessary complexity - -**Proposed Solution:** -Replace color codes with simple text markers: -- `✓` (checkmark) for success - KEEP THIS -- `✗` (x mark) for failure - KEEP THIS -- `[i]` for informational messages -- Remove color entirely, rely on symbols alone - -**Examples:** -Current: -``` -\033[0;32m✓ All unit tests passed\033[0m -\033[0;31m✗ 18 unit test file(s) failed\033[0m -\033[0;34mRunning unit tests...\033[0m -``` - -Proposed: -``` -✓ All unit tests passed -✗ 18 unit test file(s) failed -[i] Running unit tests... -``` - -**Implementation:** -1. Find all `COLOR_*` variables in Makefile -2. Replace colored text with plain text + symbols -3. Remove color variable definitions -4. Test that output is still clear and readable - -**Related Files:** -- Makefile (all COLOR_ variables and usage) - -**Success Criteria:** -- No ANSI escape codes in Makefile -- Output still clear and readable -- Uses text symbols (✓, ✗, [i]) appropriately -- Simpler, cleaner Makefile -- Test output works in any terminal/CI environment - -**Note:** -Priority [#B] because it improves readability and maintainability. Not urgent, -but makes the codebase cleaner and more portable. - -** TODO [#C] Build localrepo out (package snapshot system) +** TODO [#C] Build localrepo and document limitations Repeatable installs and safe rollbacks. -*** TODO [#C] Document localrepo limitations (treesitter grammars not included) - .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 [#C] Integrate Buttercup (behavior-driven integration tests) +** TODO [#C] Evaluate and integrate Buttercup for behavior-driven integration tests Complex workflow testing capability. -** TODO [#D] Optimize lorem-optimum performance for faster text generation +** 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. @@ -1310,129 +218,32 @@ Two benchmark tests were disabled (marked :slow) because they take MINUTES inste - tests/test-lorem-optimum-benchmark.el (tests disabled with :tags '(:slow)) - liber-primus.txt (corpus file, may need size optimization) -**Success Criteria:** -- Text generation completes in reasonable time -- Benchmark tests run in < 5 seconds -- Tests can be re-enabled without blocking test suite - -Priority [#D] because it's not breaking workflow, just slower than ideal. - - -*** TODO [#D] Optimize size of liber-primus.txt for lorem-optimum and investigate launch notices - -The liber-primus.txt file may be too large for optimal lorem-optimum performance, -causing slow random text generation or excessive memory usage. Additionally, there -are notices appearing in the *Messages* buffer during Emacs launch that need investigation. - -**Primary Problem:** -- liber-primus.txt might be too large for efficient text generation -- lorem-optimum may be slow when selecting random text from large corpus -- File size could be causing memory or performance issues -- Impact on startup time or buffer creation unknown +** TODO [#B] Build debug-profiling.el module -**Secondary Problem:** -- *Messages* buffer shows notices during Emacs launch -- May be related to lorem-optimum, liber-primus, or unrelated issues -- Need to identify source and severity of notices +Reusable profiling infrastructure for any future performance work. -**Investigation:** +** TODO [#B] Add project-aware ERT test isolation when switching projects -1. **Check current file size:** - ```bash - ls -lh liber-primus.txt - wc -l liber-primus.txt - wc -w liber-primus.txt - ``` - -2. **Review lorem-optimum configuration:** - - Find lorem-optimum module: `grep -r "lorem-optimum" modules/` - - Check how liber-primus.txt is loaded - - Look for performance issues in implementation - - Check if entire file is loaded into memory - -3. **Test performance with current file:** - ```elisp - (benchmark-run 100 - (lorem-ipsum-insert-paragraphs 1)) - ``` - - Measure baseline performance - - Note memory usage - -4. **Investigate Messages buffer notices:** - - Launch Emacs with `emacs --debug-init` - - Check *Messages* buffer immediately after startup - - Search for lorem, liber-primus, or warning keywords - - Note timestamps and context - -5. **Identify notices source:** - - Could be from lorem-optimum loading - - Could be file permissions warnings - - Could be encoding issues - - Could be unrelated initialization messages - -**Possible Solutions:** - -1. **Reduce file size** (if too large): - - Keep most meaningful/interesting sections - - Remove repetitive content - - Target size: 50-100KB (fast loading, sufficient variety) - - Preserve character of cryptic/cipher text - -2. **Optimize lorem-optimum loading** (if implementation issue): - - Lazy load: don't read file until first use - - Sample lines: don't load entire file - - Cache in memory: read once, reuse - - Stream reading: read chunks as needed - -3. **Fix launch notices** (if errors/warnings): - - Fix source of warnings - - Silence benign notices - - Add proper error handling - - Document expected behavior - -**Testing:** -1. Note baseline: file size, performance, messages -2. Apply optimization (file size or code) -3. Measure improvement: - - File size reduced? - - Performance improved? - - Messages cleaned up? -4. Verify text generation still works -5. Check variety/quality of generated text +When switching between elisp projects (e.g., emacs.d to chime.el), previously loaded +ERT tests remain in memory causing confusion and wrong tests to run. -**Related Files:** -- liber-primus.txt (the text corpus file) -- modules/lorem-optimum.el or similar (lorem generation module) -- init.el (loading sequence, Messages source) -- tests/test-lorem-optimum-*.el (performance/benchmark tests) +**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.el +- Current workaround: restart Emacs (loses session state) -**Related Docs:** -- DONE task at line 68-96: "Review lorem-optimum benchmark tests and fix" -- Failed benchmark tests may be related to this issue -- V2MOM Method 1: Frictionless (fast text generation) -- V2MOM Method 2: Stop Problems Before They Appear (clean Messages) +**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:** -- liber-primus.txt optimized to reasonable size (<100KB ideal) -- lorem-optimum generates text quickly (<100ms for paragraph) -- No unnecessary notices in *Messages* during launch -- Text generation still produces varied, interesting output -- Benchmark tests pass (after fixing per separate TODO) -- Documented optimal file size and loading strategy - -**Benchmark Target:** -- Text generation: <100ms for 1 paragraph -- File loading: <50ms at startup (if not lazy loaded) -- Memory usage: Reasonable for file size -- No degradation from current working state - -**Note:** -Priority [#B] because performance impacts daily workflow (lorem text generation -used frequently for testing) and clean *Messages* buffer is important for catching -real issues during startup. This ties into fixing the 2 failed benchmark tests -(separate TODO at line 68-96). - -* Method 4: Contribute to the Emacs Ecosystem [0/4] +- Switch projects -> old tests cleared +- Only current project's tests run with `M-x ert` +- Works with both interactive and batch runs + ** TODO [#C] Integrate undercover.el for test coverage Measure and track test coverage over time. @@ -1449,22 +260,6 @@ Catch packaging issues automatically. Zero-config CI for Emacs packages. -* Method 5: Be Kind To Your Future Self [1/2] -** DONE [#C] Add transcription workflow -CLOSED: [2025-11-12 Wed 02:41] -:PROPERTIES: -:COMPLETE_CONFIG: [[file:docs/someday-maybe.org::2][todo.org:2-99]] -:END: - -Complete code already exists in someday-maybe.org. Need today and recurring. - -** DONE [#A] Implement org-reveal presentation workflow -CLOSED: [2026-02-14 Fri] - -Created org-reveal-config.el module with ox-reveal integration for offline, -self-contained reveal.js presentations. Keybindings under C-; p prefix. -Removed pandoc-based reveal.js export from org-export-config.el. - ** TODO [#B] Create custom dupre reveal.js theme Create a custom reveal.js CSS theme using colors from themes/dupre-palette.el. @@ -1477,7 +272,6 @@ yasnippet is configured in prog-general.el, but no custom snippets directory or snippet files exist. Investigate whether snippets should be created (e.g., org structure templates for reveal.js headers, blog post front matter, etc.). -* Method 6: Develop Disciplined Engineering Practices [1/3] ** TODO [#C] Track current metrics baseline - [ ] Measure current startup time (time emacs --eval '(save-buffers-kill-emacs)') @@ -1488,58 +282,6 @@ structure templates for reveal.js headers, blog post front matter, etc.). Can't research next thing until current thing is implemented. -** DONE [#A] First weekly triage by Sunday (establish habit) -CLOSED: [2025-11-12 Wed 02:41] SCHEDULED: <2025-11-03 Sun> - -Review this inbox, cancel stale items, keep < 20 active. Track in calendar. - -* Emacs Config Inbox -** 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 [#D] Add status dashboard for dwim-shell-command processes Create a command to show all running dwim-shell-command processes with their status. @@ -1551,39 +293,10 @@ Currently, there's no unified view of multiple running extractions/conversions. - On completion: buffer renamed to `*Extract audio done*` or `*Extract audio error*` - No way to see all running processes at once -**Implementation approaches:** - -1. **Use existing process list (simplest):** - - Enhance `M-x list-processes` output filtering - - Create wrapper command that filters to dwim-shell processes only - - Pro: Uses built-in functionality - - Con: Generic process list, not tailored - -2. **Custom status buffer:** - - Create command `dwim-shell-commands-status` or similar - - Access `dwim-shell-command--commands` variable (tracks all running commands) - - Display in custom buffer with: - - Command name - - Files being processed - - Progress/status - - Time running - - Allow actions: view buffer, kill process - - Pro: Tailored UI, more useful information - - Con: More code to maintain - -3. **Mode-line indicator:** - - Show count of running dwim commands in mode-line - - Click to open status buffer - - Pro: Always visible, lightweight - - Con: Limited information at a glance - **Recommended approach:** -Start with option 2 (custom status buffer) that reads `dwim-shell-command--commands`. +Custom status buffer that reads `dwim-shell-command--commands`. Can add mode-line indicator later as enhancement. -**Files to create/modify:** -- modules/dwim-shell-config.el - add status command - ** 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.). @@ -1606,20 +319,10 @@ Need to either: - modules/flycheck-config.el (customize prefix/indicator) - modules/modeline-config.el (add to mode-line-format) -**Emoji Options:** -- Prefix: 🪰 (fly), 🐛 (bug), ✓ (check), ⚠ (warning), 🔍 (magnifier) -- Success: ✓, ✅, 🟢, ✨, 💯 - **Recommended Approach:** Option 4 (Hybrid) from spec - customize flycheck variables + add to modeline. Simple, maintainable, respects flycheck's built-in logic. -**Next Steps:** -1. Review spec document and choose emoji combination -2. Add customization to flycheck-config.el -3. Add to modeline-config.el mode-line-format -4. Test in sh-mode and emacs-lisp-mode buffers - ** TODO [#C] Investigate TRAMP/dirvish showing question marks for file dates Remote directories in dirvish show "?" instead of actual modification dates. @@ -1636,18 +339,12 @@ Tried several approaches without success - needs deeper investigation. - Could be an Emacs 29/30 + TRAMP + dirvish interaction issue - May require changes to how dirvish renders the file-size attribute on remote -**Resources:** -- https://github.com/alexluigit/dirvish/discussions/124 (related TRAMP issues) -- https://github.com/alexluigit/dirvish/blob/main/docs/CUSTOMIZING.org (TRAMP section) - **Files involved:** - modules/tramp-config.el - modules/dirvish-config.el -**Workaround:** -Use regular dired for remote directories if timestamps are needed. +** TODO [#B] Review and rebind M-S- keybindings -* 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) @@ -1669,3 +366,5 @@ These may override useful defaults - review and pick better bindings: - 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) + +* Emacs Resolved diff --git a/v2mom.org b/v2mom.org new file mode 100644 index 00000000..27b5e366 --- /dev/null +++ b/v2mom.org @@ -0,0 +1,1671 @@ +#+TITLE: Emacs Config V2MOM and Tasks +#+AUTHOR: Craig Jennings +#+DATE: 2025-10-31 +#+FILETAGS: :v2mom:active: + +* Instructions + +This inbox contains ONLY tasks that serve the V2MOM vision. Before adding any task here, ask: +1. Does it serve the Vision? +2. Does it align with the Values? +3. Is it addressed in the Methods? +4. Does it overcome an Obstacle? +5. Does it improve a Metric? + +If the answer is "no" to all five → DON'T ADD IT. + +V2MOM is located at: [[file:docs/emacs-config-v2mom.org][emacs-config-v2mom.org]] +Research/ideas that don't serve vision: [[file:docs/someday-maybe.org][someday-maybe.org]] + +* Method 1: Make Using Emacs Frictionless [16/24] +** VERIFY [#B] Fix org-noter (reading/annotation workflow currently "so painful") + +High priority - daily pain point. + +** VERIFY [#B] Fix mail attachment workflow (currently awkward) + +Daily workflow improvement. + +** DONE [#B] Optimize org-agenda performance using built-in profiler + +THE BOTTLENECK. Currently 30+ seconds, target < 5 seconds. +Use M-x profiler-start before Method 3 debug-profiling.el is built. + +** 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. + +** 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 + +** DONE [#C] Verify format-buffer hands off to shfmt in shell scripts + +Need to verify that the format-buffer command correctly delegates to shfmt when +formatting shell scripts. May not be configured or may use wrong formatter. + +**Problem:** +- Unknown if format-buffer works in shell-script-mode +- May not be using shfmt (should use shfmt for shell scripts) +- May be using a different formatter (or no formatter) +- Need to verify configuration and test manually + +**Investigation:** +1. Find format-buffer implementation: + - Search for defun format-buffer in modules/ + - Check if it's in prog-general.el or separate module + - Review how it selects formatters per mode +2. Check shfmt configuration: + - Is shfmt installed? `which shfmt` + - Is shfmt configured for shell-script-mode? + - What are the shfmt command-line arguments? +3. Test manually: + - Create test shell script with bad formatting + - Run format-buffer command + - Verify it uses shfmt (not something else) + - Check formatted output is correct + +**Expected Behavior:** +1. In shell-script-mode buffer +2. Run format-buffer (or whatever the command is) +3. Should invoke shfmt to format the buffer +4. Output should be properly formatted shell code +5. Should preserve shebang and script functionality + +**Possible Issues:** + +A. **shfmt not installed** + - Check: `pacman -Q shfmt` or `which shfmt` + - Install if missing: `sudo pacman -S shfmt` + +B. **format-buffer not configured for shell** + - May only work for elisp/python/etc. + - Need to add shell-script-mode configuration + - Need to specify shfmt command + +C. **Wrong formatter used** + - May be using bashfmt, beautysh, or other tool + - Should specifically use shfmt (preferred) + +D. **format-buffer doesn't exist** + - May be using different command name + - Check for format-all, apheleia, or custom function + +**Manual Test:** +Create test file: +```bash +#!/bin/bash +# Poorly formatted script +if [ -f "test.txt" ];then +echo "found" +else + echo "not found" +fi +for i in 1 2 3;do echo $i;done +``` + +Expected after shfmt: +```bash +#!/bin/bash +# Poorly formatted script +if [ -f "test.txt" ]; then + echo "found" +else + echo "not found" +fi +for i in 1 2 3; do + echo $i +done +``` + +**Related Commands to Check:** +- format-buffer +- format-all-buffer +- apheleia-format-buffer +- Custom cj/format-buffer + +**Related Files:** +- modules/prog-general.el (likely location of format-buffer) +- modules/prog-shell.el (shell-specific config) +- Check for apheleia or format-all package config + +**Related Docs:** +- shfmt documentation: https://github.com/mvdan/sh +- format-all or apheleia package docs (whichever is used) +- V2MOM Method 1: Frictionless (formatting should just work) + +**Success Criteria:** +- format-buffer (or equivalent) command exists +- Works in shell-script-mode buffers +- Uses shfmt as the formatter +- Produces correctly formatted shell code +- Doesn't break script functionality +- Documented what command to use and how it works + +**If It Doesn't Work:** +1. Install shfmt: `sudo pacman -S shfmt` +2. Configure formatter (apheleia or format-all): + ```elisp + ;; Example configuration + (add-to-list 'apheleia-formatters + '(shfmt . ("shfmt" "-i" "2" "-ci"))) + (add-to-list 'apheleia-mode-alist + '(shell-script-mode . shfmt)) + ``` +3. Test again +4. Document in prog-shell.el + +**Note:** +Priority [#C] because formatting is nice-to-have. Can format manually with shfmt +if needed. Low priority but good for maintaining code quality in shell scripts. + +Normal case: File with #!/bin/bash at start should get +x permission." + (let ((test-file (make-temp-file "test-script-" nil ".sh"))) + (unwind-protect + (progn + ;; Write shebang to file + (with-temp-file test-file + (insert "#!/bin/bash\necho hello\n")) + ;; Remove execute permission + (set-file-modes test-file #o644) + (should-not (file-executable-p test-file)) + ;; Open file and trigger function + (with-current-buffer (find-file-noselect test-file) + (cj/make-script-executable) + (kill-buffer)) + ;; Verify file is now executable + (should (file-executable-p test-file))) + (delete-file test-file)))) +``` + +**Related Files:** +- modules/prog-shell.el:158-167 (function to test) +- tests/test-prog-shell-make-script-executable.el (NEW - create this) +- ai-prompts/quality-engineer.org (testing guidance) + +**Related Docs:** +- quality-engineer.org: File system testing best practices +- Recent test examples: test-custom-buffer-file-*.el (file operations) +- Emacs manual: File permissions and file-modes function + +**Success Criteria:** +- Comprehensive test file covering all normal/boundary/error cases +- All tests pass on Linux +- Tests properly clean up temp files +- Tests verify actual file permission changes +- Tests verify message output +- No false positives (making non-script files executable) +- No false negatives (missing files that should be executable) +- Tests document expected behavior (serve as specification) + +**Estimated Tests:** +- 6-8 normal cases (different shebangs) +- 8-10 boundary cases (edge conditions) +- 5-6 error cases (failure handling) +- Total: ~20-25 tests + +**Note:** +Priority [#B] because this function runs on every save in shell-script-mode and +modifying file permissions incorrectly could cause security issues or workflow +problems. Needs testing before any refactoring or changes. + +** VERIFY [#C] Fix EMMS keybinding inconsistency with other buffers + +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. + +** DONE [#D] Frequently used org-mode keybindings under C-; o + +Add quick access keybindings for common org commands (org-table, org-reveal, etc.) under C-; o. +Makes org-mode operations more frictionless. +Moved from inbox 2025-11-07. + +** DONE [#A] Music player is broken - mpd/mopidy need replacement +CLOSED: [2025-11-16 Sun 18:35] SCHEDULED: <2025-11-15 Fri> + +music-config.el integration with mpd and mopidy is broken. Need to migrate to +a different music player solution. Investigate alternatives: +- emms with VLC/mpv backend +- bongo player +- Simple mpv integration +- Other lightweight music player packages + +** DONE [#A] Fix recording workflow - phone call audio not captured (44 dB volume loss) +CLOSED: [2025-11-14 Thu] + +✅ **Fixed by replacing amerge+pan with amix FFmpeg filter** + +**Problem:** +On recorded calls, only one side was captured (user's microphone), not the other person's voice. +Phone call audio was too quiet to transcribe (44 dB volume loss). + +**Root Cause:** +FFmpeg's `amerge+pan` filter combination caused massive volume loss when mixing microphone +and system monitor inputs. The `pan` filter reduced volume by 50% and `amerge` had issues +with PulseAudio/PipeWire compatibility. + +**Solution:** +Replaced `amerge=inputs=2[merged];[merged]pan=mono|c0=0.5*c0+0.5*c1` with `amix=inputs=2:duration=longest` +filter. The `amix` filter properly mixes inputs without volume loss. + +**Changes Made:** +- Changed FFmpeg filter from `amerge+pan` to `amix` (modules/video-audio-recording.el:513) +- Increased default system volume from 0.5 to 2.0 (modules/video-audio-recording.el:76) +- Added diagnostic tool `C-; r w` to show active audio playback +- Created integration test with real voice recording +- Fixed batch mode compatibility for tests + +**Results:** +- Volume improved from -66.2 dB to -21.5 dB (44 dB improvement) +- Test transcription: 100% accurate ("Can you hear me? Testing, one, two, three.") +- Phone calls now capture both sides correctly + +**Testing:** +Automated integration test verifies monitor capture works with perfect transcription. +** DONE [#A] Fix Google Calendar password prompts every 15 minutes +CLOSED: [2025-11-11 Mon] + +✅ **Fixed oauth2-auto caching bug** + +**Root Cause:** +oauth2-auto.el version 20250624.1919 had a bug on line 206 that completely +disabled its internal token cache with `or nil`. This forced every org-gcal +sync to decrypt oauth2-auto.plist from disk, triggering GPG passphrase prompts +every ~15 minutes. + +**The Bug:** +```elisp +;; Line 201-213 in oauth2-auto.el (BEFORE fix) +(defun oauth2-auto--plstore-read (username provider) + "Read the data for USERNAME and PROVIDER from the cache, else from plstore." + (let ((id (oauth2-auto--compute-id username provider))) + ; Assume cache is invalidated. FIXME + (or nil ;(gethash id oauth2-auto--plstore-cache) ;; BUG: cache disabled! + (let ((plstore (plstore-open oauth2-auto-plstore))) + ...)))) +``` + +**The Fix:** +Enabled the internal hash-table cache by removing `or nil`: +```elisp +;; Line 201-213 in oauth2-auto.el (AFTER fix) +(defun oauth2-auto--plstore-read (username provider) + "Read the data for USERNAME and PROVIDER from the cache, else from plstore." + (let ((id (oauth2-auto--compute-id username provider))) + ;; FIXED: Enable cache to prevent repeated GPG passphrase prompts + (or (gethash id oauth2-auto--plstore-cache) ;; Cache now works! + (let ((plstore (plstore-open oauth2-auto-plstore))) + ...)))) +``` + +**What Changed:** +1. Modified elpa/oauth2-auto-20250624.1919/oauth2-auto.el:201-213 +2. Removed `or nil` that disabled cache +3. Added `cj/clear-oauth2-auto-cache` helper function in auth-config.el +4. Documented fix in auth-config.el commentary (lines 16-22) + +**Result:** +- GPG passphrase prompted ONCE per Emacs session (when first accessing tokens) +- oauth2-auto now caches tokens in memory (oauth2-auto--plstore-cache) +- No more interruptions during org-gcal auto-sync every 30 minutes +- Workflow is now frictionless as intended + +**Testing:** +After restart: +1. First org-gcal sync prompts for passphrase (expected) +2. Subsequent syncs use cached tokens (no prompts) +3. Cache persists until Emacs closes + +**Files Modified:** +- elpa/oauth2-auto-20250624.1919/oauth2-auto.el (cache fix) +- modules/auth-config.el (documentation + helper function) + +Priority [#A] because password prompts every 15 minutes violated "Frictionless" value. +Fixed 2025-11-11. + +** DONE [#A] Fix audio recording device selection - still broken with Jabra headset +CLOSED: [2025-11-11 Mon] + +✅ **Fixed audio recording bug + improved UX** + +**Root Cause:** +Auto-detection only looked for `analog.*stereo` which matched laptop audio but never +Bluetooth/Jabra devices. User was always recording from laptop mic (silent when using Jabra). + +**What Was Fixed:** + +1. **Removed broken auto-detection** (lines 58-77) + - Old code only detected built-in laptop audio + - Never detected Bluetooth/USB/Jabra devices + - This is why recordings were silent + +2. **Force explicit device selection on first use** + - C-; r a now prompts for device setup if not configured + - Suggests quick setup (C-; r c) by default + - Device selection persists across Emacs sessions + +3. **Simplified keybindings to toggle start/stop** + - C-; r a → Toggle audio recording (start/stop) + - C-; r v → Toggle video recording (start/stop) + - Removed separate stop keybindings (A, V) + - One key to remember, press again to stop! + +4. **Added device testing functions** (lines 233-314) + - C-; r t b → Test both mic + monitor (guided, RECOMMENDED) + - C-; r t m → Test microphone only (5 sec) + - C-; r t s → Test system audio/monitor only (5 sec) + - Catch hardware issues before important recordings + +5. **Added modeline recording indicator** + - 🔴Audio appears when recording audio + - 🔴Video appears when recording video + - 🔴A+V appears when recording both + - Indicator and toggle always in sync (same process variables) + - Process sentinel auto-clears on crash/kill + +**New Workflow:** +``` +Press C-; r a + ↓ +First time? → Device setup → Choose Jabra → Start (🔴Audio appears) + ↓ +Already configured? → Start immediately (🔴Audio appears) + ↓ +Press C-; r a again → Stop (🔴 disappears) +``` + +**Files Modified:** +- modules/video-audio-recording.el (removed auto-detect, added tests, toggle functions, modeline indicator) +- modules/modeline-config.el (added 🔴 recording indicator to right side) + +**Testing:** +After Emacs restart: +1. Press C-; r a +2. Choose "Bluetooth Headset" (Jabra) +3. See 🔴Audio in modeline +4. Speak and play audio +5. Press C-; r a to stop +6. Verify recording has audio + +Priority [#A] because blocked daily recording and transcription workflows. +Fixed 2025-11-11. + +** DONE [#A] Remove network check from startup (saves 1+ seconds) +CLOSED: [2025-10-31 Fri] + +✅ Deleted blocking ping check. Startup improved from 6.2s to 5.4s. +Now uses package priorities: .localrepo (200) > online repos (25). + +** DONE [#A] Fix cj/goto-git-gutter-diff-hunks (missing function causing errors) +CLOSED: [2025-11-03 Sun] + +✅ Implemented missing function in modules/vc-config.el +- Added `cj/goto-git-gutter-diff-hunks` function (lines 118-124) +- Uses consult-line to search for diff markers (^[+\-]) +- Enables interactive jumping to any changed line via C-; v d +- Function properly documented with docstring +- No linting issues, compiles cleanly + +Quick win completed - 5 minutes actual time. + +** DONE [#A] Fix chime-check throw with no catch block +CLOSED: [2025-11-01 Fri] + +Error: "(no-catch --cl-block-chime-check-- nil)" +Chime was throwing to a catch block that doesn't exist. +Location: chime package - chime-check() function at line 1540 +Fix: Changed defun to cl-defun to provide implicit catch block for cl-return-from. + +Fixed in ~/code/chime.el/chime.el:1540 + +Added regression test: test-integration-startup-early-return-on-validation-failure +Created Makefile with test targets (unit, integration, all, by-file, by-name) +Updated README.org with Development/Testing section + +All integration tests pass (5/5) ✅ + +** DONE [#A] Implement cj/diff-buffer-with-file (compare buffer with saved version) +CLOSED: [2025-10-31 Fri] + +Bound to C-; b D. Weekly need satisfied. + +** DONE [#A] Add comprehensive test coverage for video-audio-recording module +CLOSED: [2025-11-03 Sun] + +✅ Created comprehensive test suite following quality-engineer.org standards: +- 9 test files (8 unit + 1 integration) +- 83 test cases with 100% pass rate +- Test categories: Normal, Boundary, Error cases +- 6 test fixtures for reproducible testing +- Mocking strategy using cl-letf +- Integration test validates complete parse→group→friendly-names workflow +- Tests document bugs in legacy detect functions +- Critical validation: Bluetooth MAC normalization across component boundaries + +✅ Refactored code for testability: +- Extracted `cj/recording--parse-pactl-output` internal parser +- Separated I/O from business logic + +✅ Fixed all linting warnings (checkdoc): +- 6 spacing/grammar issues resolved +- `make lint` now passes cleanly + +✅ All changes committed and pushed to all remotes (origin + github) + +Commits: +- 0a69c58: test: Add comprehensive test suite for video-audio-recording module +- b086539: style: Fix checkdoc warnings in video-audio-recording.el + +*** DONE [#C] Add device testing command cj/recording-test-devices +CLOSED: [2026-02-06 Thu] +Records 3 seconds of audio. +Plays it back. +Confirms devices work before real recording. + +*** CANCELLED [#C] Add recording status display (optional via flag, default off) +CLOSED: [2026-02-14 Sat] +Emoji modeline icon is sufficient. + +*** CANCELLED [#C] Add recording presets +CLOSED: [2026-02-14 Sat] +Only used for meetings; emoji icon is good-enough reminder. Gold-plating. + +*** CANCELLED [#C] Build recording history buffer +CLOSED: [2026-02-14 Sat] +Opening recordings in dirvish is sufficient. + +*** TODO [#C] Add post-processing hooks +Auto-compress after recording. +Move to cloud sync directory. +Generate transcript (once transcription workflow exists). + +** DONE [#A] Delay in modeline lines and columns update +CLOSED: [2025-11-08 Fri] + +✅ Fixed modeline position lag by replacing expensive function calls with cached values. + +**Problem:** +- Line/column numbers lagged behind cursor movement +- Used `line-number-at-pos` which counts from buffer start on every update +- Performance degraded in large files + +**Solution:** +- Replaced with built-in format specifiers `%l` and `%c` (modeline-config.el:81) +- These use cached values maintained by line-number-mode and column-number-mode +- Explicitly enabled line-number-mode in ui-config.el:53 +- Zero performance overhead - cached values update instantly + +**Result:** +- Modeline position now updates instantly with cursor movement +- No lag, even in large files +- Maintains same "L:line C:col" format + +** DONE [#B] Toggle org-appear on/off +CLOSED: [2025-11-16 Sat] + +✅ **Implemented toggle function with C-c C-a keybinding** + +Created `cj/org-appear-toggle` function that toggles org-appear-mode on/off in +current org buffer. Default is OFF (cleaner for reading), can be toggled ON when +editing links, then toggled OFF again. + +**Implementation:** +- Removed :disabled flag and :hook (default: OFF) +- Created cj/org-appear-toggle function with clear user feedback +- Bound to C-c C-a in org-mode-map (unbound, no conflicts) +- Tested: toggles correctly, all tests pass + +**Usage:** +- C-c C-a: Toggle on/off +- Default: OFF (links and emphasis markers stay hidden) +- Messages show current state clearly + +Moved from inbox 2025-11-07. Completed 2025-11-16. + +** DONE [#B] Consider implementing cron download of Google Calendar to replace org-gcal +CLOSED: [2025-11-16 Sat] + +Replaced problematic org-gcal OAuth workflow with calendar-sync.el module. +Implemented pure Elisp .ics parser with timer-based sync (no cron needed). + +**Current Problem:** +From TODO at line 22-66: +- org-gcal prompts for password every ~15 minutes +- OAuth token refresh bypasses cache +- plstore symmetric encryption cache issues +- Interrupts workflow constantly +- Makes calendar sync painful instead of seamless + +**Proposed Solution:** +Instead of OAuth-based sync (org-gcal), use Google Calendar's public iCalendar URLs: +1. Download .ics file via cron (every 15-30 minutes) +2. Parse .ics file into org-mode format +3. Update org-agenda files automatically +4. No OAuth, no passwords, no interruptions + +**Benefits:** +- ✓ No password prompts (public calendar URL or one-time API key) +- ✓ No OAuth token refresh issues +- ✓ Runs in background (cron), never interrupts work +- ✓ Simpler architecture (download → parse → update) +- ✓ Can work offline (reads last downloaded .ics) +- ✓ More reliable (fewer moving parts) +- ✓ No plstore symmetric encryption issues + +**Drawbacks:** +- ✗ Read-only (can't create/update events from Emacs) +- ✗ Need to manually get calendar iCal URL +- ✗ Requires cron setup (one-time configuration) +- ✗ May have sync delay (up to cron interval) + +**Investigation:** + +1. **Get Google Calendar iCal URL:** + - Open Google Calendar settings + - Find "Integrate calendar" section + - Copy secret iCal address (https://calendar.google.com/calendar/ical/...) + - Store in auth-source (encrypted) + +2. **Test iCal download:** + ```bash + curl -o calendar.ics "https://calendar.google.com/calendar/ical/.../basic.ics" + ``` + - Verify it downloads + - Check .ics format + - Confirm events are present + +3. **Research iCal parsing:** + - Does Emacs have built-in iCal parser? (icalendar.el) + - Check icalendar-import-file function + - Test parsing downloaded .ics file + - Verify it creates org entries + +4. **Design cron workflow:** + ```bash + # Every 15 minutes + */15 * * * * curl -s "$(cat ~/.calendar-url)" -o ~/calendars/gcal.ics + ``` + - Downloads silently in background + - Emacs watches file for changes (file-notify) + - Auto-reimport when changed + +**Possible Implementations:** + +A. **Full replacement (recommended):** + - Remove org-gcal entirely + - Use cron + icalendar.el + - Read-only calendar view in org-agenda + - Create events directly in Google Calendar web UI + +B. **Hybrid approach:** + - Keep org-gcal for writing events + - Use cron download for reading events + - Disable org-gcal auto-sync (no password prompts) + - Manually trigger org-gcal only when creating events + +C. **Enhanced cron:** + - Cron downloads .ics + - Emacs function parses and updates org files + - Add file-notify watcher for auto-update + - Optional: Convert two-way with CalDAV later + +**Implementation Sketch:** +```elisp +(defun cj/calendar-import-gcal () + "Import Google Calendar from downloaded .ics file." + (interactive) + (let ((ics-file "~/calendars/gcal.ics") + (org-file "~/org/calendar.org")) + (when (file-exists-p ics-file) + (icalendar-import-file ics-file org-file) + (message "Imported calendar from %s" ics-file)))) + +;; Auto-import when .ics file changes +(file-notify-add-watch + "~/calendars/gcal.ics" + '(change) + (lambda (event) (cj/calendar-import-gcal))) +``` + +**Related Files:** +- modules/org-gcal-config.el (current problematic implementation) +- Emacs built-in: icalendar.el (iCal parsing) +- System: crontab -e (download schedule) +- ~/.authinfo.gpg (store calendar URL securely) + +**Related Docs:** +- Current problem: TODO line 22-66 (password prompts every 15 min) +- icalendar.el manual: C-h f icalendar-import-file +- Google Calendar iCal format documentation +- V2MOM Method 1: Frictionless (no interruptions!) + +**Success Criteria:** +- Calendar events appear in org-agenda +- No password prompts during work +- Updates automatically in background (cron) +- Can work offline with last sync +- Setup is one-time configuration +- Simpler than current org-gcal setup + +**Testing Plan:** +1. Get iCal URL from Google Calendar +2. Test download: `curl URL -o test.ics` +3. Test import: `M-x icalendar-import-file` +4. Verify org entries created correctly +5. Set up cron job +6. Wait for auto-update +7. Confirm events in org-agenda +8. Disable org-gcal auto-sync +9. Monitor for 1 week (no password prompts?) + +**Decision Point:** +This is a significant architectural change. Need to: +1. Test proof-of-concept first (manual download + import) +2. Evaluate if read-only is acceptable +3. Compare to fixing OAuth password prompts +4. Consider hybrid approach if two-way sync needed + +**Note:** +Priority [#B] because this could eliminate the #1 daily irritant (password prompts +every 15 minutes). If proof-of-concept works, this is higher value than fixing +OAuth issues. Simpler architecture = fewer problems. + +** DONE [#B] Add time-zones package for quick timezone lookups +CLOSED: [2025-11-14 Fri 02:42] + +IRRITANT: Need to frequently check time differences between cities (London, Lisbon, +New Orleans, San Francisco) for meetings and coordination. Currently requires stopping +work, searching web/using external app, context switching back. + +**Pain Point:** +Multiple times per week, need to know "what time is it in London right now?" or +"if I schedule this for 2pm my time, what time is that in Lisbon?" This breaks +flow and requires leaving Emacs. + +**Solution:** +Use time-zones package: https://github.com/xenodium/time-zones + +Built-in world-clock exists (M-x world-clock) but lacks two critical features: +1. Can't interactively add cities with fuzzy search +2. Can't shift time forward/backward to check future times + +time-zones package adds both features - making timezone checks instant and frictionless. + +**Expected Workflow:** +- M-x time-zones (or keybinding C-; T z or similar) +- Interactively add/remove cities with completion +- Shift time forward/backward to check meeting times +- Stay in Emacs, maintain flow + +**Files:** +- Create new module: modules/time-zones-config.el +- Add require to init.el in appropriate section +- Configure default cities list (London, Lisbon, New Orleans, San Francisco) +- Add keybinding (suggest C-; T z for time zones) + +**V2MOM Alignment:** +Method 1 - Frictionless: Eliminates context switch for common timezone queries. +Intuitive value: Quick keybinding for frequent operation. + +** DONE [#B] Fix go-ts-mode-map keybinding error (void-variable) +CLOSED: [2025-11-03 Sun] + +Error: "Debugger entered--Lisp error: (void-variable go-ts-mode-map)" +Location: modules/prog-go.el - trying to bind keys before mode loads. + +✅ Already fixed in commit 196b289 (Nov 2, 2025) +- Moved keybinding from `:bind (:map go-ts-mode-map ...)` to hook function +- Keybinding now set in `cj/go-mode-keybindings` called via `:hook` +- Function executes after mode loads, ensuring keymap exists +- Today's cleanup: Removed unused forward declarations (lines 34-35) + +Fix was: Wrap keybinding in hook function instead of :bind clause. +Result: No more void-variable error, keybinding works correctly. + +** DONE [#B] Fix video/audio recording module (use constantly, just broke) +CLOSED: [2025-11-03 Sun] + +Main issue: No way to select audio devices when multiple are available. +Plugging in external audio interface broke recording - only captured input, not output. + +✅ COMPLETED - Module now has robust device detection and selection. + +*** DONE [#A] Add diagnostic command cj/recording-list-devices +CLOSED: [2025-11-03 Sun] + +✅ Created `cj/recording-list-devices` command (C-; r d) +Shows ALL available PulseAudio/PipeWire sources with drivers and states. +Displays current configuration. +Helps debug why auto-detection fails. + +*** DONE [#A] Add device selection UI +CLOSED: [2025-11-03 Sun] + +✅ Created TWO selection workflows: +1. `cj/recording-select-devices` (C-; r s) - Full manual control + - Select mic and system audio separately + - Interactive completion with device states +2. `cj/recording-quick-setup-for-calls` (C-; r c) - Quick call setup + - Smart device pairing (groups mic + monitor by hardware) + - One selection for both mic and system audio + - Handles Bluetooth MAC normalization + +Devices cached in variables for future recordings. +Can switch devices without restarting Emacs. + +*** DONE [#B] Improve error messages +CLOSED: [2025-11-03 Sun] + +✅ Error messages now include: +- Guidance to run `cj/recording-select-devices` +- Clear indication when auto-detection fails +- User-friendly prompts for manual selection + +*** DONE [#B] Make device detection more flexible +CLOSED: [2025-11-03 Sun] + +✅ Implemented multi-level fallback system: +1. Auto-detect using pactl output parsing +2. Prompt user to select manually if auto-detect fails +3. Error with helpful guidance if user declines + +✅ Smart device grouping in `cj/recording-group-devices-by-hardware`: +- Handles USB, PCI (built-in), and Bluetooth devices +- Normalizes Bluetooth MAC addresses (colons ↔ underscores) +- Assigns friendly names (e.g., "Built-in Laptop Audio", "Bluetooth Headset") +- Filters incomplete devices (must have both mic and monitor) + +✅ Supports both PulseAudio and PipeWire (both use pactl). + +*** TODO [#B] Validate recording startup +Check process status after starting. +Parse ffmpeg output for errors. +Show actual ffmpeg command for debugging. + +** DONE [#C] Fix grammar checker performance (currently disabled) +CLOSED: [2025-11-04 Mon] + +✅ **Installed and configured LanguageTool for comprehensive grammar checking** + +Replaced disabled grammar checker with on-demand LanguageTool integration: +- Installed LanguageTool 6.6-2 from Arch repos (222MB) +- Created wrapper script: scripts/languagetool-flycheck (Python 3) +- Integrated with flycheck for on-demand checking via C-; ? +- Removed proselint (redundant - LanguageTool catches more) +- No performance impact: only runs when explicitly invoked +- Installation instructions added to modules/flycheck-config.el commentary + +LanguageTool catches: +- Real grammar errors (subject-verb agreement, tense, etc.) +- Missing punctuation (commas, periods) +- Common mistakes (could of → could have) +- Style issues (redundant phrases, wordiness) + +Workflow: Open org/text/markdown file → press C-; ? → see errors in *Flycheck errors* buffer + +** DONE [#C] cj/flyspell-then-abbrev loses keybinding in scratch org-mode buffer +CLOSED: [2025-11-08 Fri] + +✅ Fixed keybinding issue in org-mode buffers. + +**Problem:** +1. Autoload cookies were just comments and never executed +2. Org-mode was overriding C-' with org-cycle-agenda-files + +**Solution:** +- Set keybindings directly when module loads (lines 239-240) +- Explicitly override org-mode's C-' after org loads (lines 244-245) +- Both C-' and C-c f now work correctly in all buffers including org-mode + +File modified: modules/flyspell-and-abbrev.el:235-251 + +* Method 2: Stop Problems Before They Appear [4/8] +** TODO [#B] Write Complete ERT Tests for This Config [0/31] +Unit and Integration Tests should be added as subtasks below, marked done when complete. + +*High-value test targets (no coverage, testable logic, daily use):* + +*** TODO custom-case — pure case conversion functions (upper/lower/title) +*** TODO custom-datetime — date/timestamp insertion and formatting +*** TODO host-environment — platform detection (env-macos-p, env-wayland-p, etc.) +*** TODO hugo-config — draft toggle, slug generation, post template +*** TODO org-capture-config — template building (relates to capture perf optimization) +*** TODO modeline-config — custom segment construction +*** TODO external-open — file-type detection and external app dispatch +*** TODO reconcile-open-repos — dirty repo scanning logic +*** TODO media-utils — URL download/play logic +*** TODO org-config — org-mode utility functions +*** TODO org-export-config — export helper functions +*** TODO local-repository — package snapshot logic +*** TODO show-kill-ring — kill ring display logic +*** TODO system-commands — reboot/logout/system action functions +*** TODO config-utilities — debug helper functions + +*Modules with partial coverage (expand existing tests):* + +*** TODO org-agenda-config — caching/TTL logic untested (only build-list covered) +*** TODO org-contacts-config — expand beyond capture/parse +*** TODO prog-shell — expand beyond make-script-executable +*** TODO ui-config — expand beyond buffer-status/cursor-color +*** TODO org-refile-config — expand beyond build-targets +*** TODO org-webclipper — expand beyond process (only 1 test file) +*** TODO org-noter-config — expand beyond generate-notes/title-to-slug +*** TODO browser-config — expand beyond current single test file +*** TODO flycheck-config — expand beyond languagetool setup +*** TODO org-drill-config — expand beyond first-function/font-switching + +*Lower priority (testable but less critical):* + +*** TODO chrono-tools — timer/clock functions +*** TODO help-utils — search dispatch (arch-wiki, devdoc, tldr, wikipedia) +*** TODO dirvish-config — wallpaper setter, custom functions +*** TODO dwim-shell-config — shell command definitions +*** TODO elfeed-config — podcast/feed helper functions +*** TODO eww-config — browser helper functions + +** 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) + +**Related Files:** +- modules/system-lib.el (target file) +- modules/host-environment.el (likely source) +- modules/system-utils.el (likely source) +- modules/config-utilities.el (check for candidates) +- tests/test-system-lib-*.el (add tests for moved functions) + +**Related Docs:** +- Recent refactoring: Created system-lib.el with cj/executable-exists-p +- Testing guidance: ai-prompts/quality-engineer.org +- V2MOM Method 2: Stop Problems Before They Appear (better organization) + +**Success Criteria:** +- All generic system utilities consolidated in system-lib.el +- Each function has comprehensive test coverage +- No functionality broken (all tests pass) +- Documentation explains purpose and scope of system-lib.el +- Other modules properly require system-lib where needed + +** 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. + +** DONE [#B] Move cj/log-silently to system-lib +CLOSED: [2025-11-16 Sun 18:36] + +The `cj/log-silently` function is a generic utility for logging messages without +displaying them in the echo area. It should be moved to system-lib.el for better +organization and reusability across modules. + +**Current Problem:** +- cj/log-silently is likely defined in a specific module +- It's a generic logging utility that could be used by any module +- Not easily discoverable for reuse +- Doesn't follow the system-lib pattern we're establishing + +**What is cj/log-silently?** +This function logs messages to the *Messages* buffer without interrupting the user +by displaying them in the echo area (minibuffer). Useful for debugging and tracing +code execution without breaking user flow. + +**Task:** +1. **Find current location:** + ```bash + grep -rn "defun cj/log-silently" modules/ + ``` + +2. **Review implementation:** + - Check if it has dependencies on mode-specific functionality + - Verify it's truly generic (should be) + - Check for any callers that need updating + +3. **Move to system-lib.el:** + - Cut from current location + - Paste into system-lib.el + - Add appropriate commentary/docstring + - Ensure proper section organization + +4. **Update callers:** + - Find all uses: `grep -rn "cj/log-silently" modules/` + - Add `(require 'system-lib)` to any module that uses it + - Verify no circular dependencies + +5. **Write tests:** + Create `tests/test-system-lib-log-silently.el` with coverage for: + - Normal cases: logging simple messages + - Boundary cases: empty strings, very long messages, special characters + - Error cases: nil input, non-string input + - Verify output: check *Messages* buffer contains logged text + - Verify silence: ensure nothing appears in echo area + +**Expected Signature:** +```elisp +(defun cj/log-silently (format-string &rest args) + "Log a message to *Messages* buffer without displaying in echo area. +FORMAT-STRING and ARGS work like `message' but output is not shown to user." + (let ((inhibit-message t)) + (apply #'message format-string args))) +``` + +**Related Files:** +- modules/system-lib.el (destination) +- Current module where cj/log-silently lives (TBD - find it) +- All modules that call cj/log-silently (update requires) +- tests/test-system-lib-log-silently.el (NEW - create this) + +**Related Docs:** +- System-lib refactoring initiative (previous TODO) +- quality-engineer.org (testing guidance) +- Recent refactoring: moved cj/executable-exists-p to system-lib +- V2MOM Method 2: Stop Problems Before They Appear (better organization) + +**Success Criteria:** +- cj/log-silently moved to system-lib.el +- All callers updated with proper requires +- Comprehensive test coverage (normal/boundary/error cases) +- All existing tests still pass (no regressions) +- Function works identically to before +- Well-documented in system-lib.el + +**Testing:** +1. Run all tests before move (baseline) +2. Move function and update requires +3. Run all tests after move (verify no breakage) +4. Run new cj/log-silently tests (verify behavior) +5. Test in real usage (logging works, messages not shown) + +**Note:** +Priority [#B] because this is part of the larger system-lib consolidation effort +(separate TODO). Logging utilities are commonly used, so centralizing them improves +discoverability and encourages consistent logging patterns across the codebase. + +** DONE [#C] Switch to mood-line (actually: built custom modeline) +CLOSED: [2025-11-03 Sun] + +✅ **Built custom modeline (better than mood-line)** + +Went beyond mood-line and created a fully custom modeline using only built-in +Emacs functionality to avoid native-compilation issues. Features: + +**Architecture:** +- Named segment system using defvar-local (easy to reorder) +- Emacs 30 built-in right-alignment (mode-line-format-right-align) +- All segments marked as risky-local-variable for proper evaluation + +**Interactive Features:** +- Color-coded buffer names (green=writeable, red=read-only, gold=overwrite) +- VC branch with git symbol () and state-based coloring +- Mouse click handlers: buffer name (prev/next), branch (vc-diff), mode (describe-mode) +- Help-echo tooltips on all segments +- String truncation for narrow windows (< 100 chars wide) +- Active-window-only display for branch and misc-info (less clutter) + +**Layout:** +- Left: Major mode, buffer name, position (L:# C:#) +- Right: Git branch, chime notifications + +**Bug Fixes:** +- Disabled async native compilation (prevented "Selecting deleted buffer" errors) +- Fixed difftastic loading (:demand → :defer) +- Abstracted buffer status colors to user-constants.el + +Inspired by Prot's modeline design. See commit c0c4b17. + +** DONE [#C] Remove deprecated tree-sitter package (rely on treesit-auto) +CLOSED: [2025-11-03 Sun] + +✅ Removed deprecated tree-sitter package from modules/prog-general.el +- Deleted `(use-package tree-sitter)` on line 97 +- Now relies solely on Emacs 29+ built-in treesit with treesit-auto +- treesit-auto continues to manage tree-sitter grammars automatically +- No functionality lost, cleaner dependency tree + +** DONE [#C] Add org-appear (show emphasis markers only when point is on them) +CLOSED: [2025-11-03 Sun] + +✅ Added org-appear package to modules/org-config.el +- Shows emphasis markers (* / _) only when cursor is on them +- Also shows link markup and sub/superscripts when editing +- Changed org-fontify-emphasized-text from nil to t (line 75) +- Updated comment on line 71 to reference org-appear +- Cleaner editing experience while maintaining visual clarity + +* Method 3: Make *Fixing* Emacs Frictionless [0/9] +** DONE [#A] Write tests for cj/make-script-executable (suspected broken) +CLOSED: [2025-11-11 Tue] + +The `cj/make-script-executable` function automatically makes shell scripts executable +when they have a shebang, but has no test coverage. **Suspected to be broken/not working.** +This is a critical function that modifies file permissions and runs on every save. + +**Function Location:** +modules/prog-shell.el:158-167 + +**Why This Matters:** +1. Runs automatically on after-save-hook in shell-script-mode (high frequency) +2. Modifies file permissions (security-relevant) +3. If broken, scripts won't become executable automatically +4. No test coverage means bugs go undetected + +**Investigation First:** +1. Test manually: Create test.sh with `#!/bin/bash`, save, check if executable +2. Check if function is actually hooked to after-save-hook +3. Verify conditions in function logic are correct +4. Look for any error messages in *Messages* buffer + +**Then Write Tests:** +Following quality-engineer.org patterns: +- Normal cases: Various shebangs (bash, python, ruby, etc.) +- Boundary cases: Shebang with spaces, not at start, already executable +- Error cases: No file, read-only filesystem, permission errors + +**Estimated Work:** +- Manual testing: 15 minutes +- Writing comprehensive tests: 2-3 hours +- ~20-25 tests total + +**Success Criteria:** +- Confirm function works or identify bug +- Comprehensive test coverage +- Tests document expected behavior +- Can refactor safely with tests as safety net + +Priority [#B] because if broken, it's a daily workflow issue (scripts don't auto-execute). +Moved from inbox 2025-11-11. + +** DONE [#A] Fix difftastic integration - not showing semantic diffs (just unified diff) +CLOSED: [2025-11-11 Tue] + +Difftastic was marked as "integrated" but diffs in magit and custom-buffer-file.el look +identical to standard unified diffs. **Likely not actually using difftastic** - probably +falling back to git diff or missing a configuration switch. + +**Problem:** +Two places where difftastic should work but doesn't: +1. **Magit diffs** - Should show semantic diffs with D/S keybindings, but looks like unified diff +2. **Buffer diff** (custom-buffer-file.el) - cj/diff-buffer-with-file should use difftastic but looks like unified diff + +**Investigation:** +1. Check if difftastic binary actually gets called: + - Test: `difft --version` (verify binary exists) + - Test: `difft file1.el file2.el` manually to see what output looks like + - Should show syntax-aware, tree-based diff (very different from unified) + +2. Review vc-config.el difftastic setup (lines ~176-190): + - Is difftastic.el package loaded? (check with `M-x package-list-packages`) + - Are keybindings actually bound? (check magit-diff-mode-map) + - Is there a configuration switch we're missing? + +3. Check custom-buffer-file.el: + - Claims to use ediff (line 554-565), not difftastic + - Confusion: Is it supposed to use difftastic or ediff? + - If ediff, that's different tool (interactive split-screen, not semantic) + +**Possible Issues:** +A. difftastic.el not actually loaded (:defer preventing it) +B. Missing transient menu configuration for magit +C. Need to enable difftastic-mode explicitly +D. Keybindings shadowed by other bindings +E. ANSI color codes not rendering (looks wrong but is difftastic) + +**Expected Behavior:** +Difftastic output should look VERY different from unified diff: +- Tree-based syntax matching +- Side-by-side or structured format +- Language-aware (knows it's elisp/org/etc) +- Shows matched nodes, not just line changes + +**Next Steps:** +1. Run difft manually on two .el files to see expected output +2. Try calling difftastic functions directly: `M-x difftastic-magit-diff` +3. Check *Messages* for errors when using D/S in magit +4. Review difftastic.el documentation for required configuration + +**Related Files:** +- modules/vc-config.el (difftastic config) +- modules/custom-buffer-file.el (buffer diff - might be ediff, not difftastic?) +- Binary: /usr/bin/difft + +**Success Criteria:** +- Diffs in magit show obvious semantic/structural differences +- Output clearly different from unified diff +- Can visually identify it's difftastic (not git diff) +- Documented how to use and what to expect + +Priority [#B] because if not working, we're not getting the benefit of difftastic integration. +Moved from inbox 2025-11-11. + +** TODO [#B] Build debug-profiling.el module + +Reusable profiling infrastructure for any future performance work. +** TODO [#C] Evaluate Buttercup for integration tests +** TODO [#B] Add project-aware ERT test isolation when switching projects + +When switching between elisp projects (e.g., emacs.d to chime.el), 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.el +- 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 + +Priority [#B] because affects daily workflow when working on multiple elisp projects. +Moved from inbox 2025-11-11. + +** DONE [#B] Remove ANSI color codes from Makefile - breaks test output readability +CLOSED: [2025-11-11 Tue] + +ANSI color codes render incorrectly in some terminals, making test output unreadable. +Can see it's colored red, but can't read what the actual error message says due to +escape code littering throughout the text. Blocks debugging. + +**Problem:** +- Makefile uses variables like `COLOR_GREEN`, `COLOR_RED`, `COLOR_BLUE` +- These insert ANSI escape codes like `\033[0;32m` into output +- Makes output harder to read, especially in logs or when piped +- Color codes don't work well in all terminals +- Unnecessary complexity + +**Proposed Solution:** +Replace color codes with simple text markers: +- `✓` (checkmark) for success - KEEP THIS +- `✗` (x mark) for failure - KEEP THIS +- `[i]` for informational messages +- Remove color entirely, rely on symbols alone + +**Examples:** +Current: +``` +\033[0;32m✓ All unit tests passed\033[0m +\033[0;31m✗ 18 unit test file(s) failed\033[0m +\033[0;34mRunning unit tests...\033[0m +``` + +Proposed: +``` +✓ All unit tests passed +✗ 18 unit test file(s) failed +[i] Running unit tests... +``` + +**Implementation:** +1. Find all `COLOR_*` variables in Makefile +2. Replace colored text with plain text + symbols +3. Remove color variable definitions +4. Test that output is still clear and readable + +**Related Files:** +- Makefile (all COLOR_ variables and usage) + +**Success Criteria:** +- No ANSI escape codes in Makefile +- Output still clear and readable +- Uses text symbols (✓, ✗, [i]) appropriately +- Simpler, cleaner Makefile +- Test output works in any terminal/CI environment + +**Note:** +Priority [#B] because it improves readability and maintainability. Not urgent, +but makes the codebase cleaner and more portable. + +** TODO [#C] Build localrepo out (package snapshot system) + +Repeatable installs and safe rollbacks. + +*** TODO [#C] Document localrepo limitations (treesitter grammars not included) + +.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 [#C] Integrate Buttercup (behavior-driven integration tests) + +Complex workflow testing capability. + +** TODO [#D] Optimize lorem-optimum performance for faster text generation + +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) + +**Success Criteria:** +- Text generation completes in reasonable time +- Benchmark tests run in < 5 seconds +- Tests can be re-enabled without blocking test suite + +Priority [#D] because it's not breaking workflow, just slower than ideal. + + +*** TODO [#D] Optimize size of liber-primus.txt for lorem-optimum and investigate launch notices + +The liber-primus.txt file may be too large for optimal lorem-optimum performance, +causing slow random text generation or excessive memory usage. Additionally, there +are notices appearing in the *Messages* buffer during Emacs launch that need investigation. + +**Primary Problem:** +- liber-primus.txt might be too large for efficient text generation +- lorem-optimum may be slow when selecting random text from large corpus +- File size could be causing memory or performance issues +- Impact on startup time or buffer creation unknown + +**Secondary Problem:** +- *Messages* buffer shows notices during Emacs launch +- May be related to lorem-optimum, liber-primus, or unrelated issues +- Need to identify source and severity of notices + +**Investigation:** + +1. **Check current file size:** + ```bash + ls -lh liber-primus.txt + wc -l liber-primus.txt + wc -w liber-primus.txt + ``` + +2. **Review lorem-optimum configuration:** + - Find lorem-optimum module: `grep -r "lorem-optimum" modules/` + - Check how liber-primus.txt is loaded + - Look for performance issues in implementation + - Check if entire file is loaded into memory + +3. **Test performance with current file:** + ```elisp + (benchmark-run 100 + (lorem-ipsum-insert-paragraphs 1)) + ``` + - Measure baseline performance + - Note memory usage + +4. **Investigate Messages buffer notices:** + - Launch Emacs with `emacs --debug-init` + - Check *Messages* buffer immediately after startup + - Search for lorem, liber-primus, or warning keywords + - Note timestamps and context + +5. **Identify notices source:** + - Could be from lorem-optimum loading + - Could be file permissions warnings + - Could be encoding issues + - Could be unrelated initialization messages + +**Possible Solutions:** + +1. **Reduce file size** (if too large): + - Keep most meaningful/interesting sections + - Remove repetitive content + - Target size: 50-100KB (fast loading, sufficient variety) + - Preserve character of cryptic/cipher text + +2. **Optimize lorem-optimum loading** (if implementation issue): + - Lazy load: don't read file until first use + - Sample lines: don't load entire file + - Cache in memory: read once, reuse + - Stream reading: read chunks as needed + +3. **Fix launch notices** (if errors/warnings): + - Fix source of warnings + - Silence benign notices + - Add proper error handling + - Document expected behavior + +**Testing:** +1. Note baseline: file size, performance, messages +2. Apply optimization (file size or code) +3. Measure improvement: + - File size reduced? + - Performance improved? + - Messages cleaned up? +4. Verify text generation still works +5. Check variety/quality of generated text + +**Related Files:** +- liber-primus.txt (the text corpus file) +- modules/lorem-optimum.el or similar (lorem generation module) +- init.el (loading sequence, Messages source) +- tests/test-lorem-optimum-*.el (performance/benchmark tests) + +**Related Docs:** +- DONE task at line 68-96: "Review lorem-optimum benchmark tests and fix" +- Failed benchmark tests may be related to this issue +- V2MOM Method 1: Frictionless (fast text generation) +- V2MOM Method 2: Stop Problems Before They Appear (clean Messages) + +**Success Criteria:** +- liber-primus.txt optimized to reasonable size (<100KB ideal) +- lorem-optimum generates text quickly (<100ms for paragraph) +- No unnecessary notices in *Messages* during launch +- Text generation still produces varied, interesting output +- Benchmark tests pass (after fixing per separate TODO) +- Documented optimal file size and loading strategy + +**Benchmark Target:** +- Text generation: <100ms for 1 paragraph +- File loading: <50ms at startup (if not lazy loaded) +- Memory usage: Reasonable for file size +- No degradation from current working state + +**Note:** +Priority [#B] because performance impacts daily workflow (lorem text generation +used frequently for testing) and clean *Messages* buffer is important for catching +real issues during startup. This ties into fixing the 2 failed benchmark tests +(separate TODO at line 68-96). + +* Method 4: Contribute to the Emacs Ecosystem [0/4] +** 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. + +* Method 5: Be Kind To Your Future Self [1/2] +** DONE [#C] Add transcription workflow +CLOSED: [2025-11-12 Wed 02:41] +:PROPERTIES: +:COMPLETE_CONFIG: [[file:docs/someday-maybe.org::2][todo.org:2-99]] +:END: + +Complete code already exists in someday-maybe.org. Need today and recurring. + +** DONE [#A] Implement org-reveal presentation workflow +CLOSED: [2026-02-14 Fri] + +Created org-reveal-config.el module with ox-reveal integration for offline, +self-contained reveal.js presentations. Keybindings under C-; p prefix. +Removed pandoc-based reveal.js export from org-export-config.el. + +** TODO [#B] 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. + +** TODO [#B] Investigate missing yasnippet configuration + +snippets-dir is defined in user-constants.el (points to org-dir/snippets/) and +yasnippet is configured in prog-general.el, but no custom snippets directory or +snippet files exist. Investigate whether snippets should be created (e.g., org +structure templates for reveal.js headers, blog post front matter, etc.). + +* Method 6: Develop Disciplined Engineering Practices [1/3] +** TODO [#C] Track current metrics baseline + +- [ ] Measure current startup time (time emacs --eval '(save-buffers-kill-emacs)') +- [ ] Count current active todos +- [ ] Set up tracking document for weekly metrics + +** TODO [#C] Set up monthly research:shipped ratio tracking + +Can't research next thing until current thing is implemented. + +** DONE [#A] First weekly triage by Sunday (establish habit) +CLOSED: [2025-11-12 Wed 02:41] SCHEDULED: <2025-11-03 Sun> + +Review this inbox, cancel stale items, keep < 20 active. Track in calendar. + +* Emacs Config Inbox +** 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 [#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 + +**Implementation approaches:** + +1. **Use existing process list (simplest):** + - Enhance `M-x list-processes` output filtering + - Create wrapper command that filters to dwim-shell processes only + - Pro: Uses built-in functionality + - Con: Generic process list, not tailored + +2. **Custom status buffer:** + - Create command `dwim-shell-commands-status` or similar + - Access `dwim-shell-command--commands` variable (tracks all running commands) + - Display in custom buffer with: + - Command name + - Files being processed + - Progress/status + - Time running + - Allow actions: view buffer, kill process + - Pro: Tailored UI, more useful information + - Con: More code to maintain + +3. **Mode-line indicator:** + - Show count of running dwim commands in mode-line + - Click to open status buffer + - Pro: Always visible, lightweight + - Con: Limited information at a glance + +**Recommended approach:** +Start with option 2 (custom status buffer) that reads `dwim-shell-command--commands`. +Can add mode-line indicator later as enhancement. + +**Files to create/modify:** +- modules/dwim-shell-config.el - add status command + +** 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] 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) + +**Emoji Options:** +- Prefix: 🪰 (fly), 🐛 (bug), ✓ (check), ⚠ (warning), 🔍 (magnifier) +- Success: ✓, ✅, 🟢, ✨, 💯 + +**Recommended Approach:** +Option 4 (Hybrid) from spec - customize flycheck variables + add to modeline. +Simple, maintainable, respects flycheck's built-in logic. + +**Next Steps:** +1. Review spec document and choose emoji combination +2. Add customization to flycheck-config.el +3. Add to modeline-config.el mode-line-format +4. Test in sh-mode and emacs-lisp-mode buffers + +** 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 + +**Resources:** +- https://github.com/alexluigit/dirvish/discussions/124 (related TRAMP issues) +- https://github.com/alexluigit/dirvish/blob/main/docs/CUSTOMIZING.org (TRAMP section) + +**Files involved:** +- modules/tramp-config.el +- modules/dirvish-config.el + +**Workaround:** +Use regular dired for remote directories if timestamps are needed. + +* 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) |
