No Wayman <iarchivedmywholel...@gmail.com> writes:
The attached patch is the first step toward integrating DOCT[1]
syntax into Org mode.
It adds property options to org-capture-templates which make it
easier to run template-specific hooks.
The current approach for running such hooks involves adding to
the
desired global hook variable and filtering by the template's
keys.
e.g.
#+begin_src emacs-lisp :lexical t
(defun +example-template-hook ()
(when (eq (org-capture-get :key t) "e")
(message "hook run")))
(add-hook 'org-capture-mode-hook #'+example-template-hook)
(let ((org-capture-templates '("e" "example" (file "") "")))
(org-capture nil "e"))
#+end_src
The hook has to be maintained separately from the template
declaration.
The criteria to determine the selected template is baked into
the
hook function.
This is fragile (change the binding for the template and you
must
update the hook function),
mixes concerns, and makes templates harder to share.
Contrast the above with the following syntax enabled by the
attached patch:
#+begin_src emacs-lisp :lexical t
(let ((org-capture-templates
'(("t" "test" plain (file "/tmp/test.org")
"test %?"
:hook ((lambda () (insert "mode-hook\n")))
:before-finalize ((lambda () (insert
"before-finalize\n")))
;; Only a message because this happens outside the
context
;; of the capture buffer.
:after-finalize ((lambda () (message
"after-finalize")))
:prepare-finalize ((lambda () (insert
"prepare-finalize\n")))))))
(org-capture nil "t"))
#+end_src
These template-specific hook functions run prior to their global
counterparts.
Ihor, an implementation note: I have not used `run-hooks' with
these because they have no associated symbol.
The functions are lists stored directly on `org-capture-plist'.
[1]: https://github.com/progfolio/doct
And, of course, the patch...
>From 790e8c517ba933025e50302e9c990ccf9265b55c Mon Sep 17 00:00:00 2001
From: Nicholas Vollmer <iarchivedmywholel...@gmail.com>
Date: Tue, 27 Sep 2022 05:44:33 -0400
Subject: [PATCH] org-capture: Add template hook properties
* lisp/org-capture.el (org-capture-templates): Document template hook properties.
(org-capture-finalize): execute :prepare/:before/:after-finalize functions.
(org-capture-place-template): execute :hook functions.
* doc/org-manual.org Document template hook properties.
---
doc/org-manual.org | 20 ++++++++++++++++++++
lisp/org-capture.el | 21 +++++++++++++++++++++
2 files changed, 41 insertions(+)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index ab8a295e5..ed2322949 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -7838,6 +7838,26 @@ Now lets look at the elements of a template definition. Each entry in
- ~:refile-targets :: Temporarily set ~org-refile-targets~ to the
value of this property.
+ - ~:hook~ ::
+
+ A list of functions run before `org-capture-mode-hook'
+ when the template is selected.
+
+ - ~:prepare-finalize~ ::
+
+ A list of functions run before `org-capture-prepare-finalize-hook'
+ when the template is selected.
+
+ - ~:before-finalize~ ::
+
+ A list of functions run before `org-capture-before-finalize-hook'
+ when the template is selected.
+
+ - ~:after-finalize~ ::
+
+ A list of functions run before `org-capture-after-finalize-hook'
+ when the template is selected.
+
**** Template expansion
:PROPERTIES:
:DESCRIPTION: Filling in information about time and context.
diff --git a/lisp/org-capture.el b/lisp/org-capture.el
index 428d0ac0e..af1502ede 100644
--- a/lisp/org-capture.el
+++ b/lisp/org-capture.el
@@ -297,6 +297,21 @@ properties are:
:no-save Do not save the target file after finishing the capture.
+ :hook A list of functions run before
+ `org-capture-mode-hook' when the template is selected.
+
+ :prepare-finalize A list of functions run before
+ `org-capture-prepare-finalize-hook'
+ when the template is selected.
+
+ :before-finalize A list of functions run before
+ `org-capture-before-finalize-hook'
+ when the template is selected.
+
+ :after-finalize A list of functions run before
+ `org-capture-after-finalize-hook'
+ when the template is selected.
+
The template defines the text to be inserted. Often this is an
Org mode entry (so the first line should start with a star) that
will be filed as a child of the target headline. It can also be
@@ -751,6 +766,7 @@ captured item after finalizing."
(buffer-base-buffer (current-buffer)))
(error "This does not seem to be a capture buffer for Org mode"))
+ (mapc #'funcall (org-capture-get :prepare-finalize t))
(run-hooks 'org-capture-prepare-finalize-hook)
;; Update `org-capture-plist' with the buffer-local value. Since
@@ -823,6 +839,7 @@ captured item after finalizing."
;; the indirect buffer has been killed.
(org-capture-store-last-position)
+ (mapc #'funcall (org-capture-get :before-finalize t))
;; Run the hook
(run-hooks 'org-capture-before-finalize-hook))
@@ -871,6 +888,9 @@ captured item after finalizing."
;; Restore the window configuration before capture
(set-window-configuration return-wconf))
+ ;; Do not use the local arg to `org-capture-get' here.
+ ;; The buffer-local has been stored on `org-capture-plist'.
+ (mapc #'funcall (org-capture-get :after-finalize))
(run-hooks 'org-capture-after-finalize-hook)
;; Special cases
(cond
@@ -1147,6 +1167,7 @@ may have been stored before."
(`item (org-capture-place-item))
(`checkitem (org-capture-place-item)))
(setq-local org-capture-current-plist org-capture-plist)
+ (mapc #'funcall (org-capture-get :hook t))
(org-capture-mode 1))
(defun org-capture-place-entry ()
--
2.37.3