fix(org-noter): definitive fix -- repair wrong NOTER_DOCUMENT + cl-letf prompt bypass
This commit is contained in:
82
config.el
82
config.el
@@ -1249,58 +1249,66 @@ Otherwise: runs interactive ement-connect, then opens rooms after sync."
|
||||
org-noter-insert-note-no-questions nil
|
||||
org-noter-use-indirect-buffer nil))
|
||||
|
||||
;; Smart org-noter launcher: always works from a PDF buffer.
|
||||
;; Pre-creates the notes file with correct NOTER_DOCUMENT (relative path),
|
||||
;; then starts org-noter from the notes file (org-mode context) to avoid
|
||||
;; org-noter's file-search which requires parent-directory relationship.
|
||||
;; Smart org-noter launcher: finds the PDF window, repairs broken notes files,
|
||||
;; and auto-answers org-noter's prompts so sessions start without user interaction.
|
||||
;; Uses absolute NOTER_DOCUMENT paths (avoids symlink issues with file-relative-name).
|
||||
(defun my/org-noter-start ()
|
||||
"Start org-noter for the PDF visible in the current frame.
|
||||
Creates the notes file with a correct NOTER_DOCUMENT property (relative path)
|
||||
if it does not already exist, then starts the session from the notes buffer."
|
||||
Repairs any existing notes file with a wrong NOTER_DOCUMENT property,
|
||||
then starts the session — no interactive prompts required."
|
||||
(interactive)
|
||||
;; Ensure org-noter is loaded so its variables are available
|
||||
(require 'org-noter)
|
||||
(let* ((pdf-win (if (derived-mode-p 'pdf-view-mode)
|
||||
(selected-window)
|
||||
(cl-find-if
|
||||
(lambda (w)
|
||||
(cl-find-if (lambda (w)
|
||||
(with-current-buffer (window-buffer w)
|
||||
(derived-mode-p 'pdf-view-mode)))
|
||||
(window-list (selected-frame)))))
|
||||
(pdf-path (when pdf-win
|
||||
(with-current-buffer (window-buffer pdf-win)
|
||||
(buffer-file-name)))))
|
||||
(if (not pdf-path)
|
||||
;; No PDF buffer found — fall back to standard org-noter
|
||||
(org-noter)
|
||||
(unless pdf-path
|
||||
(user-error "No PDF buffer visible — open a PDF first"))
|
||||
(let* ((base (file-name-base pdf-path))
|
||||
(notes-dir (expand-file-name "notes/" org-directory))
|
||||
(notes-file (expand-file-name (concat base ".org") notes-dir))
|
||||
;; Relative path from notes file dir to PDF (what org-noter stores)
|
||||
(rel-path (file-relative-name pdf-path notes-dir)))
|
||||
(notes-name (concat base ".org"))
|
||||
(notes-dir (car org-noter-notes-search-path))
|
||||
(target (expand-file-name notes-name notes-dir)))
|
||||
(make-directory notes-dir t)
|
||||
;; Create or update notes file — insert NOTER_DOCUMENT as relative path
|
||||
(with-current-buffer (find-file-noselect notes-file)
|
||||
(when (= (buffer-size) 0)
|
||||
;; New file: create a proper org-noter heading
|
||||
(insert (format "* Notes: %s\n:PROPERTIES:\n:NOTER_DOCUMENT: %s\n:END:\n\n"
|
||||
base rel-path))
|
||||
(save-buffer))
|
||||
(unless (save-excursion
|
||||
;; Repair existing notes file if NOTER_DOCUMENT is wrong (doesn't point to pdf-path).
|
||||
;; Uses absolute path for NOTER_DOCUMENT to avoid symlink resolution issues.
|
||||
(when (file-exists-p target)
|
||||
(with-current-buffer (find-file-noselect target)
|
||||
(let ((modified nil))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(re-search-forward ":NOTER_DOCUMENT:" nil t))
|
||||
;; Existing file without property: prepend heading
|
||||
(goto-char (point-min))
|
||||
(insert (format "* Notes: %s\n:PROPERTIES:\n:NOTER_DOCUMENT: %s\n:END:\n\n"
|
||||
base rel-path))
|
||||
(save-buffer)))
|
||||
;; Open notes file and start org-noter from there (org-mode context)
|
||||
;; This uses the simpler code path that reads NOTER_DOCUMENT directly
|
||||
(find-file notes-file)
|
||||
(goto-char (point-min))
|
||||
(re-search-forward ":NOTER_DOCUMENT:" nil t)
|
||||
(org-back-to-heading t)
|
||||
(org-noter)))))
|
||||
(while (re-search-forward
|
||||
(concat "^[ \t]*:" org-noter-property-doc-file ":[ \t]*\\(.*\\)$")
|
||||
nil t)
|
||||
(let* ((stored (string-trim (match-string 1)))
|
||||
(expanded (if (file-name-absolute-p stored)
|
||||
stored
|
||||
(expand-file-name stored (file-name-directory target)))))
|
||||
(unless (and (file-exists-p expanded)
|
||||
(file-equal-p expanded pdf-path))
|
||||
;; Wrong or missing target — replace with absolute path to PDF
|
||||
(replace-match (concat ":" org-noter-property-doc-file
|
||||
": " pdf-path)
|
||||
t t)
|
||||
(setq modified t)))))
|
||||
(when modified (save-buffer)))))
|
||||
;; Auto-answer org-noter's two interactive prompts:
|
||||
;; "What name do you want the notes to have?" -> notes-name (basename.org)
|
||||
;; "Where do you want to save it?" -> target (notes-dir/basename.org)
|
||||
;; org-noter will then create the heading with the correct NOTER_DOCUMENT itself.
|
||||
(cl-letf* ((orig-cr (symbol-function 'completing-read))
|
||||
((symbol-function 'completing-read)
|
||||
(lambda (prompt collection &rest args)
|
||||
(cond
|
||||
((string-match-p "name" prompt) notes-name)
|
||||
((string-match-p "save\\|where\\|Which" prompt) target)
|
||||
(t (apply orig-cr prompt collection args))))))
|
||||
(with-selected-window pdf-win
|
||||
(org-noter))))))
|
||||
|
||||
(map! :leader
|
||||
(:prefix ("o" . "open")
|
||||
|
||||
Reference in New Issue
Block a user