Skip to content

Commit

Permalink
Merge branch 'feature/sync-noter-document' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
petermao committed Jun 25, 2023
2 parents b157534 + 8df9905 commit d654838
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 1 deletion.
2 changes: 2 additions & 0 deletions modules/org-noter-djvu.el
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
(require 'djvu)
(error (message "ATTENTION: org-noter-djvu needs the package `djvu'")))

(push "djvu" org-noter--doc-extensions)

(defun org-noter-djvu--pretty-print-location (location)
(org-noter--with-valid-session
(when (eq (org-noter--session-doc-mode session) 'djvu-read-mode)
Expand Down
2 changes: 2 additions & 0 deletions modules/org-noter-nov.el
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
(require 'nov)
(error (message "ATTENTION: org-noter-nov needs the package `nov'")))

(push "epub" org-noter--doc-extensions)

(defvar nov-documents-index)
(defvar nov-file-name)
(defvar-local org-noter--nov-timer nil
Expand Down
1 change: 1 addition & 0 deletions modules/org-noter-pdf.el
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
(require 'pdf-tools)
(error (message "ATTENTION: org-noter-pdf has many featues that depend on the package `pdf-tools'")))

(push "pdf" org-noter--doc-extensions)
(cl-defstruct pdf-highlight page coords)

(defun org-noter-pdf--get-highlight ()
Expand Down
92 changes: 91 additions & 1 deletion org-noter-core.el
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@
:group 'org-noter
:type '(repeat symbol))

(defvar org-noter--doc-extensions nil
"List of extensions handled by org-noter when documents are moved.
Used by `org-noter--sync-doc-rename-in-notes'. This variable gets filled in by supported modes, so it is not a `defcustom' variable.")

(defcustom org-noter-property-doc-file "NOTER_DOCUMENT"
"Name of the property that specifies the document."
:group 'org-noter
Expand Down Expand Up @@ -1662,7 +1666,7 @@ DOCUMENT-PATH is a path to a document file."
(insert-file-contents notes-path)
(catch 'break
(while (re-search-forward (org-re-property org-noter-property-doc-file) nil t)
(when (file-equal-p (expand-file-name (match-string 3) (file-name-directory notes-path))
(when (string-equal (expand-file-name (match-string 3) (file-name-directory notes-path))
document-path)
;; NOTE(nox): This notes file has the document we want!
(throw 'break t)))))))
Expand Down Expand Up @@ -1734,6 +1738,92 @@ mode."
This is delegated to each document mode (eg pdf)."
(run-hook-with-args-until-success 'org-noter--pretty-print-highlight-location-hook highlight-location))

(defun org-noter--sync-doc-rename-in-notes (document-path new-document-path &optional _ok-if-already-exists)
"Update org-noter references to document-file whose name has changed.
DOCUMENT-PATH is the original filename.
NEW-DOCUMENT-PATH is the new filename.
This advice runs after `dired-rename-file' completes successfully
on files with `file-name-extension' in `org-noter--doc-extensions'.
For notes files that have the same `file-name-base' as the
document, the notes filename will be changed, but not its
`file-name-directory'.
If the document is moved to a path above the notes file, a
warning will be issued, but the sync will proceed. The directory
of the notes file will not be changed, as there may be other
documents referenced in the notes file. An `org-noter' session
can still be initiated from the notes file, but not vice-versa,
nor will future renames of the document be synced in the notes
file.
"
(when (and (member-ignore-case (file-name-extension document-path)
org-noter--doc-extensions)
(not (file-exists-p document-path))
(file-exists-p new-document-path))
;; continue if the file extension is that of a document
;; and the rename was successful
(let* ((document-name (file-name-nondirectory document-path))
(document-base (file-name-base document-name))
(document-directory (file-name-directory document-path))

(search-names (remove nil (append org-noter-default-notes-file-names
(list (concat document-base ".org"))
(list (run-hook-with-args-until-success 'org-noter-find-additional-notes-functions document-path)))))
notes-files ; list of notes files with promising names (Notes.org or <docname>.org)
notes-path) ; junk variable when iterating over notes-files

;; find promising notes files by name in a few places...
(dolist (name search-names)
;; check the notes-search-paths
(dolist (path org-noter-notes-search-path)
(setq notes-path (expand-file-name name path))
(when (file-exists-p notes-path)
(push notes-path notes-files)))
;; check paths at or above document-directory
(let ((directory (locate-dominating-file document-directory name)))
(when directory
(setq notes-path (expand-file-name name directory))
(push notes-path notes-files))))

(setq notes-files (delete-dups notes-files))

;; in each annotating notes file, find the entry for this file and update
;; the document's relative path
(dolist (notes-path notes-files)
(when (org-noter--check-if-document-is-annotated-on-file document-path notes-path)
(with-temp-buffer
(insert-file-contents notes-path)
(org-with-point-at (point-min)
(catch 'break ;stop when we find a match
(while (re-search-forward (org-re-property org-noter-property-doc-file) nil)
(let ((property-value (match-string 3))
(notes-directory (file-name-directory notes-path)))
(when (string-equal (expand-file-name property-value notes-directory)
document-path)
(let ((doc-relative-name (file-relative-name new-document-path notes-directory))
msg)
;; sync the new document path in this notes file
(org-set-property org-noter-property-doc-file doc-relative-name)
;; warn against docs that reside above notes in path
(when (string-prefix-p "../" doc-relative-name)
(setq msg
(format-message "Document file has moved above notes file (%s). `org-noter' will not be able to find the notes file from the new document path (%s)." notes-path doc-relative-name))
(display-warning 'org-noter msg :warning)))
(write-file notes-path nil)
;; change the notes filename if it was based on the document filename
(if (string-equal (file-name-base notes-path) document-base)
(let ((new-notes-path (concat (file-name-directory notes-path)
(file-name-base new-document-path) ".org")))
(rename-file notes-path new-notes-path)))
(throw 'break t))))))))))))

(advice-add 'dired-rename-file :after 'org-noter--sync-doc-rename-in-notes)
;;uncomment or eval next line to disable.
;;(advice-remove 'dired-rename-file 'org-noter--sync-doc-rename-in-notes)

;; --------------------------------------------------------------------------------
;;; User commands
(defun org-noter-set-start-location (&optional arg)
Expand Down

0 comments on commit d654838

Please sign in to comment.