forked from weirdNox/org-noter
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'org-noter/master' into dev
- Loading branch information
Showing
6 changed files
with
250 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,5 @@ | |
|
||
(depends-on "log4e") | ||
(depends-on "undercover") | ||
|
||
(depends-on "org-roam") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
;;; org-noter-org-roam --- org-roam support for org-noter -*- lexical-binding: t; -*- | ||
|
||
;; Copyright (C) 2023 Dmitry Markushevich | ||
|
||
;; This file is not part of GNU Emacs. | ||
|
||
;; This program is free software; you can redistribute it and/or modify | ||
;; it under the terms of the GNU General Public License as published by | ||
;; the Free Software Foundation, either version 3 of the License, or | ||
;; (at your option) any later version. | ||
|
||
;; This program is distributed in the hope that it will be useful, | ||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
;; GNU General Public License for more details. | ||
|
||
;; You should have received a copy of the GNU General Public License | ||
;; along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
;;; Commentary: | ||
|
||
;; This module adds org-roam integration to org-noter | ||
|
||
;;; Code: | ||
|
||
(require 'cl-lib) | ||
(require 'org-roam-node) | ||
|
||
(defun org-noter--get-filename-for-org-roam-node () | ||
"Use org-roam to specify a node." | ||
(let* ((templates (list (append (car org-roam-capture-templates) '(:immediate-finish t)))) | ||
(node (org-roam-node-read)) | ||
(_ (org-roam-capture- | ||
:node node | ||
:info nil | ||
:templates templates | ||
:props nil)) | ||
(node-id (org-roam-node-id node)) | ||
(file-path-for-new-entry (org-roam-node-file (org-roam-node-from-id node-id)))) | ||
(message "%s" file-path-for-new-entry) | ||
file-path-for-new-entry)) | ||
|
||
|
||
(defun org-noter--create-session-from-document-file-supporting-org-roam | ||
(&optional arg doc-path) | ||
"Main point of integration with org-noter. | ||
This is a hook function that is to be assigned | ||
to `org-noter-create-session-from-document-hook' to enable org-roam integration: | ||
`(setq org-noter-create-session-from-document-hook '(org-noter--create-session-from-document-file-supporting-org-roam)' | ||
Alternatively, you can call the `org-noter-enable-org-roam-integration'. | ||
ARG is not current used but here for compatibility reasons. | ||
DOC-PATH is the path to the document (pdf)." | ||
(let* ((file-path-for-org-roam-node (org-noter--get-filename-for-org-roam-node)) | ||
(_ (message "[d] opening up notes: %s doc: %s" file-path-for-org-roam-node doc-path)) | ||
;; create or find a top level heading for the document and return it | ||
(top-level-heading-for-doc-position (with-current-buffer (find-file-noselect file-path-for-org-roam-node) | ||
(org-noter--find-create-top-level-heading-for-doc doc-path (file-name-base doc-path))))) | ||
(message "going to pos: %s" top-level-heading-for-doc-position) | ||
(with-current-buffer (find-file-noselect file-path-for-org-roam-node) | ||
(goto-char top-level-heading-for-doc-position) | ||
(org-noter)))) | ||
|
||
|
||
|
||
|
||
(defun org-noter--find-top-level-heading-for-document-path (doc-path) | ||
"Given a DOC-PATH check to see if there's a top level heading for it. | ||
It returns the point for the heading (if found) \"nil\" otherwise." | ||
(let ((found-heading-position nil)) | ||
(org-with-point-at (point-min) | ||
(condition-case nil | ||
;; look for NOTER_DOCUMENT property that matches the doc-path | ||
(while (and (not found-heading-position) | ||
(re-search-forward (org-re-property org-noter-property-doc-file))) | ||
(let ((current-file-name (expand-file-name (match-string 3))) | ||
(looking-for-filename (expand-file-name doc-path))) | ||
(when (file-equal-p current-file-name looking-for-filename) | ||
(setq found-heading-position (point))))) | ||
(search-failed ;; when re=search-forward hits the end it throws an error which we should catch | ||
(message "This buffer doesn't seem to have a matching NOTER_DOCUMENT heading.") nil))) | ||
found-heading-position)) | ||
|
||
|
||
(defun org-noter--find-create-top-level-heading-for-doc (doc-path desired-heading) | ||
"In current buffer, look for a top level heading for document at DOC-PATH. | ||
If one is not found, DESIRED-HEADING is created and it's position is returned" | ||
(let* ((top-level-heading-for-doc-position (org-noter--find-top-level-heading-for-document-path doc-path))) | ||
;; does this buffer have a top level notes heading for this document? | ||
(if (eq top-level-heading-for-doc-position nil) | ||
(org-noter--create-notes-heading desired-heading doc-path) | ||
top-level-heading-for-doc-position))) | ||
|
||
|
||
;; TODO How is this different from org-noter--insert-heading? | ||
;; org-noter--insert-heading doesn't deal with top level headings. | ||
(defun org-noter--create-notes-heading (notes-heading document-path) | ||
"Create a top level notes heading for the document. | ||
NOTES-HEADING is the headline, DOCUMENT-PATH is used for the | ||
NOTER_DOCUMENT property. Return the point where the heading was inserted." | ||
(cl-assert notes-heading t "notes-heading cannot be nil. we can't insert a nil heading.") | ||
(goto-char (point-max)) | ||
(insert (if (save-excursion (beginning-of-line) (looking-at "[[:space:]]*$")) "" "\n") | ||
"* " notes-heading ) | ||
(org-entry-put nil org-noter-property-doc-file | ||
(expand-file-name document-path)) | ||
(point)) | ||
|
||
|
||
|
||
(provide 'org-noter-org-roam) | ||
|
||
;;; org-noter-org-roam.el ends here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
;; Dmitry M <[email protected]> | ||
;; Homepage: https://github.com/org-noter/org-noter | ||
;; Keywords: lisp pdf interleave annotate external sync notes documents org-mode | ||
;; Package-Requires: ((emacs "24.4") (cl-lib "0.6") (org "9.0")) | ||
;; Package-Requires: ((emacs "24.4") (cl-lib "0.6") (org "9.4")) | ||
;; Version: 1.5.0 | ||
|
||
;; This file is not part of GNU Emacs. | ||
|
@@ -308,6 +308,14 @@ marked file." | |
(bury-buffer)) | ||
(other-frame 1))) | ||
|
||
|
||
(defun org-noter-enable-org-roam-integration () | ||
"Enable org-roam integration." | ||
(interactive) | ||
(load "org-noter-org-roam") | ||
(setq org-noter-create-session-from-document-hook | ||
'(org-noter--create-session-from-document-file-supporting-org-roam))) | ||
|
||
(provide 'org-noter) | ||
|
||
;;; org-noter.el ends here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
(require 'org-noter-test-utils) | ||
(require 'org-noter-org-roam) | ||
|
||
(describe "org-roam integration" | ||
(before-each | ||
(create-org-noter-test-session) | ||
) | ||
|
||
(describe "org-roam" | ||
(before-each | ||
;; org-noter uses file-equal-p that looks at the filesystem. We need real files to verify this functionality. | ||
(shell-command "mkdir -p /tmp/pubs/ && touch /tmp/pubs/solove-nothing-to-hide.pdf && touch /tmp/test.pdf")) | ||
|
||
(describe "top level heading insertion" | ||
(it "can insert a top level heading at the end of the file" | ||
(with-mock-contents | ||
mock-contents-simple-notes-file | ||
'(lambda () | ||
(org-noter--create-notes-heading "ADOCUMENT" "/tmp/file") | ||
(expect (string-match "ADOCUMENT" (buffer-string)) :not :to-be nil) | ||
(expect (string-match "/tmp/file" (buffer-string)) :not :to-be nil) | ||
;; ADOCUMENT should come after solove-nothing-to-hide | ||
(expect (string-match "solove-nothing-to-hide" (buffer-string)) :to-be-less-than | ||
(string-match "ADOCUMENT" (buffer-string))) | ||
(message (buffer-string))))) | ||
|
||
(it "can find an existing heading without creating a new one" | ||
(with-mock-contents | ||
mock-contents-simple-notes-file | ||
'(lambda () | ||
(let* ((found-heading-pos (org-noter--find-create-top-level-heading-for-doc "/tmp/test.pdf" "solove-nothing-to-hide"))) | ||
(message "\n00 ----") | ||
(goto-char found-heading-pos) | ||
(insert "!!") | ||
(message (buffer-string)) | ||
(message "\n00 ----") | ||
|
||
(expect found-heading-pos :to-be 141) | ||
(message "----") | ||
(message (buffer-string)) | ||
(message "---- %s" (length (buffer-string))))))) | ||
|
||
|
||
(it "can create a new heading" | ||
(with-mock-contents | ||
mock-contents-simple-notes-file | ||
'(lambda () | ||
(expect | ||
;; org-noter-test-file is defined in test-utils. | ||
(org-noter--find-create-top-level-heading-for-doc "/tmp/some-other-pdf-file.pdf" "SOME HEADING") | ||
:to-be 162) | ||
(message "----") | ||
(message (buffer-string)) | ||
(message "---- %s" (length (buffer-string))) | ||
|
||
))) | ||
) | ||
|
||
|
||
(describe "identifying top level headlines" | ||
(before-each | ||
;; org-noter uses file-equal-p that looks at the filesystem. We need real files to verify this functionality. | ||
(shell-command "mkdir -p /tmp/pubs/ && touch /tmp/pubs/solove-nothing-to-hide.pdf") | ||
) | ||
|
||
(it "can find the top level headline for a specified document and return the position" | ||
(with-mock-contents | ||
mock-contents-simple-notes-file | ||
'(lambda () | ||
(message "\n11 ----") | ||
(insert "!!") | ||
(message (buffer-string)) | ||
(message "\n11 ----") | ||
(expect | ||
(org-noter--find-top-level-heading-for-document-path "/tmp/test.pdf") | ||
:to-be 143) | ||
(message (buffer-string))))) | ||
|
||
|
||
(it "return nil for a non existent top level heading" | ||
(with-mock-contents | ||
mock-contents-simple-notes-file | ||
'(lambda () | ||
(expect | ||
(org-noter--find-top-level-heading-for-document-path "/FAKE/PATH/DOESNT/EXIST") | ||
:to-be nil) | ||
(message (buffer-string))))) | ||
) | ||
|
||
|
||
|
||
|
||
) | ||
|
||
|
||
(describe "org-noter integration" | ||
(before-each | ||
;; org-noter uses file-equal-p that looks at the filesystem. We need real files to verify this functionality. | ||
(shell-command "mkdir -p /tmp/pubs/ && touch /tmp/pubs/solove-nothing-to-hide.pdf")) | ||
|
||
;; mocking a lot of stuff, for integration sake. | ||
;; ideally we'd split up functions to be somewhat smaller to ease testing. | ||
(it "executes org-noter" | ||
(spy-on 'org-noter--find-create-top-level-heading-for-doc :and-call-fake (lambda (doc-path desired-heading) 1001)) | ||
(spy-on 'org-noter--get-filename-for-org-roam-node :and-call-fake (lambda () "/tmp/pubs/notes.org")) | ||
(spy-on 'org-noter) | ||
(with-mock-contents | ||
mock-contents-simple-notes-file | ||
'(lambda () | ||
(write-region (point-min) (point-max) "/tmp/pubs/notes.org"))) | ||
(org-noter--create-session-from-document-file-supporting-org-roam nil "/tmp/pubs/solove-nothing-to-hide.pdf") | ||
(expect 'org-noter :to-have-been-called)) | ||
) | ||
|
||
(it "sets the hook correctly when org-roam integration is enabled" | ||
(org-noter-enable-org-roam-integration) | ||
(expect org-noter-create-session-from-document-hook :to-equal '(org-noter--create-session-from-document-file-supporting-org-roam))) | ||
|
||
|
||
) |