diff options
| author | Szymon Szukalski <szymon@szymonszukalski.com> | 2026-04-07 18:13:41 +1000 |
|---|---|---|
| committer | Szymon Szukalski <szymon@szymonszukalski.com> | 2026-04-07 18:13:41 +1000 |
| commit | 4fc029e3b41786ea1ad6b3aefbc3cab0f0bac769 (patch) | |
| tree | 5fae4e141f22a25e010cc6ae08fa8b2ae8a8614a | |
| parent | 550eb3ab53398b5caac72617f9afe1b359a9aa7c (diff) | |
fix: avoid rolodex hook recursion
| -rw-r--r-- | config.org | 112 |
1 files changed, 61 insertions, 51 deletions
@@ -400,32 +400,36 @@ machine-facing layer only reads heading text and properties; the =Context= and (mtime (file-attribute-modification-time attributes))) (unless (and ss/people--cache (equal mtime ss/people--cache-mtime)) - (setq ss/people--cache - (with-temp-buffer - (insert-file-contents file) - (org-mode) - (goto-char (point-min)) - (let (entries) - (org-element-map (org-element-parse-buffer) 'headline - (lambda (headline) - (when (= 1 (org-element-property :level headline)) - (goto-char (org-element-property :begin headline)) - (push (list :name (org-element-property :raw-value headline) - :abbrev (org-entry-get nil "ABBREV") - :aliases (ss/people--split-values - (org-entry-get nil "ALIASES")) - :role (org-entry-get nil "ROLE") - :location (org-entry-get nil "LOCATION") - :engagement (org-entry-get nil "ENGAGEMENT") - :relationship (org-entry-get nil "RELATIONSHIP") - :current-focus (org-entry-get nil "CURRENT_FOCUS") - :team (org-entry-get nil "TEAM")) - entries)))) - (sort entries - (lambda (left right) - (string< (ss/people--entry-name left) - (ss/people--entry-name right))))) - ss/people--cache-mtime mtime)) + (let ((entries + (with-temp-buffer + (insert-file-contents file) + ;; Parse cards without running user hooks; otherwise the + ;; rolodex's own Org hooks recurse back into this parser. + (delay-mode-hooks + (org-mode)) + (goto-char (point-min)) + (let (cards) + (org-element-map (org-element-parse-buffer) 'headline + (lambda (headline) + (when (= 1 (org-element-property :level headline)) + (goto-char (org-element-property :begin headline)) + (push (list :name (org-element-property :raw-value headline) + :abbrev (org-entry-get nil "ABBREV") + :aliases (ss/people--split-values + (org-entry-get nil "ALIASES")) + :role (org-entry-get nil "ROLE") + :location (org-entry-get nil "LOCATION") + :engagement (org-entry-get nil "ENGAGEMENT") + :relationship (org-entry-get nil "RELATIONSHIP") + :current-focus (org-entry-get nil "CURRENT_FOCUS") + :team (org-entry-get nil "TEAM")) + cards)))) + (sort cards + (lambda (left right) + (string< (ss/people--entry-name left) + (ss/people--entry-name right)))))))) + (setq ss/people--cache entries + ss/people--cache-mtime mtime))) ss/people--cache)) (defun ss/people-reload () @@ -483,10 +487,6 @@ machine-facing layer only reads heading text and properties; the =Context= and (when-let ((entry (ss/people--entry-by-name candidate))) (concat " " (ss/people--summary entry)))) - (with-eval-after-load 'marginalia - (add-to-list 'marginalia-annotator-registry - '(ss-person ss/people-marginalia-annotator builtin none))) - (defun ss/people-select-entry (&optional prompt) "Select a person entry using PROMPT." (let ((completion-extra-properties '(:annotation-function ss/people-marginalia-annotator))) @@ -520,6 +520,12 @@ machine-facing layer only reads heading text and properties; the =Context= and (file-truename ss/people-file))) (add-hook 'after-save-hook #'ss/people-reload nil t))) + (defun ss/people--source-buffer-p () + "Return non-nil when the current buffer visits `ss/people-file'." + (and buffer-file-name + (string= (file-truename buffer-file-name) + (file-truename ss/people-file)))) + (defun ss/people--open-entry (entry) "Open people.org and narrow to ENTRY." (find-file (ss/people--ensure-file)) @@ -671,15 +677,16 @@ machine-facing layer only reads heading text and properties; the =Context= and (defun ss/people-install-abbrevs () "Install people abbrevs into the current buffer." - (setq-local local-abbrev-table (copy-abbrev-table local-abbrev-table)) - (dolist (entry (ss/people-entries)) - (let ((name (ss/people--entry-name entry)) - (abbrev (ss/people--entry-abbrev entry))) - (define-abbrev local-abbrev-table - (if (or (null abbrev) (string-empty-p abbrev)) - (ss/people-default-abbrev name) - abbrev) - name)))) + (unless (ss/people--source-buffer-p) + (setq-local local-abbrev-table (copy-abbrev-table local-abbrev-table)) + (dolist (entry (ss/people-entries)) + (let ((name (ss/people--entry-name entry)) + (abbrev (ss/people--entry-abbrev entry))) + (define-abbrev local-abbrev-table + (if (or (null abbrev) (string-empty-p abbrev)) + (ss/people-default-abbrev name) + abbrev) + name))))) (defun ss/people-refresh-buffers () "Refresh people abbrevs in every prose buffer." @@ -696,20 +703,23 @@ machine-facing layer only reads heading text and properties; the =Context= and (skip-syntax-backward "w_") (let ((beg (point))) (when (< beg end) - (list beg end #'ss/people--completion-table - :exclusive 'no - :annotation-function - (lambda (candidate) - (when-let ((entry (ss/people--entry-by-name candidate))) - (concat " " (ss/people--summary entry)))) - :company-docsig - (lambda (candidate) - (when-let ((entry (ss/people--entry-by-name candidate))) - (ss/people--summary entry))))))))) + (let ((annotation + (lambda (candidate) + (when-let ((entry (ss/people--entry-by-name candidate))) + (concat " " (ss/people--summary entry))))) + (docsig + (lambda (candidate) + (when-let ((entry (ss/people--entry-by-name candidate))) + (ss/people--summary entry))))) + (list beg end #'ss/people--completion-table + :exclusive 'no + :annotation-function annotation + :company-docsig docsig))))))) (defun ss/enable-people-capf () "Add `ss/people-capf' once in prose buffers." - (unless (memq #'ss/people-capf completion-at-point-functions) + (unless (or (ss/people--source-buffer-p) + (memq #'ss/people-capf completion-at-point-functions)) (add-hook 'completion-at-point-functions #'ss/people-capf nil t))) (defun ss/people--maybe-overview-buffer () @@ -720,7 +730,7 @@ machine-facing layer only reads heading text and properties; the =Context= and (widen) (goto-char (point-min)) (org-overview) - (org-cycle-hide-drawers 'all)))) + (org-cycle-hide-drawers 'all))) (dolist (hook '(text-mode-hook org-mode-hook)) (add-hook hook #'ss/enable-people-capf) |
