(feat): clean-ups for org-roam-capture system (#315)

This introduces 2 user-facing changes:

1. If a capture process is aborted, the file is not created if it
doesn't yet exist

2. If a capture process is aborted, org-roam-insert will not insert a
link
This commit is contained in:
Jethro Kuan
2020-03-17 17:06:49 +08:00
committed by GitHub
parent 81dd880357
commit 8f8ccf6797

View File

@@ -735,6 +735,9 @@ applies.
inserted on initial creation (added only once). This is where
insertion of any note metadata should go.")
(defvar org-roam--capture-insert-link-plist nil
"Dynamically scoped variable used to insert the org link after org-capture.")
(defun org-roam--fill-template (str &optional info)
"Expands the template STR, returning the string.
This is an extension of org-capture's template expansion.
@@ -751,6 +754,16 @@ Next, it expands the remaining template string using
(completing-read (format "%s: " key ) nil))) nil)
(org-capture-fill-template)))
(defun org-roam--capture-save-file-maybe-h ()
"This function is saves the file if the original value of
:no-save is not t and `org-note-abort' is not t. It is added to
`org-capture-after-finalize-hook'."
(when (and (not (org-capture-get :orig-no-save))
(not org-note-abort))
(with-current-buffer (org-capture-get :buffer)
(save-buffer)))
(remove-hook 'org-capture-after-finalize-hook #'org-roam--capture-save-file-maybe-h))
(defun org-roam--capture-new-file ()
"Return the path to the new file during an Org-roam capture.
@@ -761,7 +774,18 @@ If the file path already exists, it throw an error.
Else, to insert the header content in the file, org-capture
template is prepended with the `:head' portion of the Org-roam
capture template."
capture template.
To prevent the creation of a new file if the capture process is
aborted, we do the following:
1. Save the original value of the capture template's :no-save.
2. Set the capture template's :no-save to t.
3. Add a function on `org-capture-after-finalize-hook' that saves
the file if the original value of :no-save is not t and
`org-note-abort' is not t."
(let* ((name-templ (or (org-capture-get :file-name)
org-roam--capture-file-name-default))
(new-id (s-trim (org-roam--fill-template
@@ -770,12 +794,14 @@ capture template."
(file-path (org-roam--file-path-from-id new-id)))
(when (file-exists-p file-path)
(error (format "File exists at %s, aborting" file-path)))
(org-capture-put :orig-no-save (org-capture-get :no-save))
(org-capture-put :template
(concat
(or (org-capture-get :head)
org-roam--capture-header-default)
(org-capture-get :template))
:type 'plain)
:type 'plain
:no-save t)
file-path))
(defun org-roam--expand-capture-template ()
@@ -801,7 +827,7 @@ This function is used solely in Org-roam's capture templates: see
('title
(let ((file-path (org-roam--capture-new-file)))
(org-roam--expand-capture-template)
(setq org-roam--capture-file-path file-path)
(org-capture-put :roam-file-path file-path)
(set-buffer (org-capture-target-buffer file-path))
(widen)
(goto-char (point-max))))
@@ -811,7 +837,7 @@ This function is used solely in Org-roam's capture templates: see
(file-path (or (cdr (assoc ref completions))
(org-roam--capture-new-file))))
(org-roam--expand-capture-template)
(setq org-roam--capture-file-path file-path)
(org-capture-put :roam-file-path file-path)
(set-buffer (org-capture-target-buffer file-path))
(widen)
(goto-char (point-max))))
@@ -822,23 +848,31 @@ This function is used solely in Org-roam's capture templates: see
The templates are defined at `org-roam-capture-templates'. The
GOTO and KEYS argument have the same functionality as
`org-capture'."
(let ((org-capture-templates org-roam-capture-templates)
file-path)
(let ((org-capture-templates org-roam-capture-templates))
(when (= (length org-capture-templates) 1)
(setq keys (caar org-capture-templates)))
(org-capture goto keys)))
;;; Interactive Commands
;;;; org-roam-insert
(defvar org-roam--capture-insert-point nil
"The point to jump to after the call to `org-roam-insert'.")
(defun org-roam--format-link-title (title)
"Retur the link title, given the file TITLE."
(if (functionp org-roam-link-title-format)
(funcall org-roam-link-title-format title)
(format org-roam-link-title-format title)))
(defun org-roam--format-link (target description)
"Formats an org link for a given file TARGET and link DESCRIPTION."
(let* ((here (-> (or (buffer-base-buffer)
(current-buffer))
(buffer-file-name)
(file-truename)
(file-name-directory))))
(format "[[%s][%s]]"
(concat "file:"
(file-relative-name target here))
description)))
(defun org-roam-insert (prefix)
"Find an Org-roam file, and insert a relative org link to it at point.
If PREFIX, downcase the title before insertion."
@@ -856,49 +890,40 @@ If PREFIX, downcase the title before insertion."
(title (org-roam--completing-read "File: " completions
:initial-input region-text))
(region-or-title (or region-text title))
(target-file-path (cdr (assoc title completions)))
(current-file-path (-> (or (buffer-base-buffer)
(current-buffer))
(buffer-file-name)
(file-truename)
(file-name-directory)))
(buf (current-buffer))
(p (point-marker)))
(unless (and target-file-path
(file-exists-p target-file-path))
(current-buffer))
(buffer-file-name)
(file-truename)
(file-name-directory)))
(target-file-path (cdr (assoc title completions)))
(link-description (org-roam--format-link-title (if prefix
(downcase region-or-title)
region-or-title))))
(if (and target-file-path
(file-exists-p target-file-path))
(progn
(when region ;; Remove previously selected text.
(delete-region (car region) (cdr region)))
(insert (org-roam--format-link target-file-path link-description)))
(let* ((org-roam--capture-info (list (cons 'title title)
(cons 'slug (org-roam--title-to-slug title))))
(org-roam--capture-context 'title))
(org-roam-capture)
(setq target-file-path org-roam--capture-file-path)
(setq org-roam--capture-file-path nil)))
(with-current-buffer buf
(when region ;; Remove previously selected text.
(delete-region (car region) (cdr region)))
(let ((link-location (concat "file:"
(file-relative-name target-file-path
current-file-path)))
(description (org-roam--format-link-title (if prefix
(downcase region-or-title)
region-or-title))))
(goto-char p)
(insert (format "[[%s][%s]]"
link-location
description))
(setq org-roam--capture-insert-point (point))))
(add-hook 'org-capture-after-finalize-hook #'org-roam--capture-advance-point)))
(add-hook 'org-capture-after-finalize-hook #'org-roam--capture-insert-link-h)
(setq org-roam--capture-insert-link-plist (list :region region
:link-description link-description))
(org-roam-capture)))))
(defun org-roam--capture-advance-point ()
"Advances the point if it is updated.
We need this function because typically `org-capture' prevents the
point from being advanced, whereas when a link is inserted, the
point moves some characters forward. This is added as a hook to
`org-capture-after-finalize-hook'."
(when org-roam--capture-insert-point
(goto-char org-roam--capture-insert-point)
(setq org-roam--capture-insert-point nil))
(remove-hook 'org-capture-after-finalize-hook #'org-roam--capture-advance-point))
(defun org-roam--capture-insert-link-h ()
"Inserts the link into the original buffer, after the capture process is done.
This is added as a hook to `org-capture-after-finalize-hook'."
(when (and (not org-note-abort)
org-roam--capture-insert-link-plist)
(when-let ((region (plist-get org-roam--capture-insert-link-plist :region))) ;; Remove previously selected text.
(delete-region (car region) (cdr region)))
(insert (org-roam--format-link (org-capture-get :roam-file-path)
(plist-get org-roam--capture-insert-link-plist :link-description)))
(setq org-roam--capture-insert-link-plist nil))
(remove-hook 'org-capture-after-finalize-hook #'org-roam--capture-insert-link-h))
;;;; org-roam-find-file
(defun org-roam--get-title-path-completions ()
@@ -915,13 +940,12 @@ point moves some characters forward. This is added as a hook to
file-path) res))))
res))
(defun org-roam--capture-find-file ()
(defun org-roam--capture-find-file-h ()
"Opens the newly created template file.
This is added as a hook to `org-capture-after-finalize-hook'."
(when org-roam--capture-file-path
(find-file org-roam--capture-file-path)
(setq org-roam--capture-file-path nil))
(remove-hook 'org-capture-after-finalize-hook #'org-roam--capture-find-file))
(when-let ((file-path (org-capture-get :roam-file-path)))
(find-file file-path))
(remove-hook 'org-capture-after-finalize-hook #'org-roam--capture-find-file-h))
(defun org-roam-find-file (&optional initial-prompt)
"Find and open an Org-roam file.
@@ -936,8 +960,8 @@ INITIAL-PROMPT is the initial title prompt."
(let* ((org-roam--capture-info (list (cons 'title title)
(cons 'slug (org-roam--title-to-slug title))))
(org-roam--capture-context 'title))
(org-roam-capture)
(add-hook 'org-capture-after-finalize-hook #'org-roam--capture-find-file)))))
(add-hook 'org-capture-after-finalize-hook #'org-roam--capture-find-file-h)
(org-roam-capture)))))
;;;; org-roam-find-ref
(defun org-roam--get-ref-path-completions ()