1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
;;; +org-capture.el -*- lexical-binding: t; -*-
;;; Code:
(require 'cl-lib)
(require 'acdw)
;; We don't require `org-capture' here because I'll have to require this library
;; to init.el /before/ org-capture is fully needed. But I do need to declare
;; `org-capture-templates'.
(defvar org-capture-templates nil)
(defun +org-capture--get (key &optional list)
"Find KEY in LIST, or return nil.
LIST defaults to `org-capture-templates'."
(alist-get key (or list org-capture-templates) nil nil #'equal))
;; Set it up as a generic value. Based on the one for `alist-get'.
(gv-define-expander +org-capture--get
(lambda (do key &optional alist)
(setq alist (or alist org-capture-templates))
(macroexp-let2 macroexp-copyable-p k key
(gv-letplace (getter setter) alist
(macroexp-let2 nil p `(assoc ,k ,getter 'equal)
(funcall do `(cdr ,p)
(lambda (v)
(macroexp-let2 nil v v
(let ((set-exp
`(if ,p (setcdr ,p ,v)
,(funcall setter
`(cons (setq ,p (cons ,k ,v))
,getter)))))
`(progn
,set-exp
,v))))))))))
(defun +org-capture-sort (&optional list)
"Sort LIST by string keys.
LIST is a symbol and defaults to `org-capture-templates'."
(setq list (or list 'org-capture-templates))
(set list (sort (symbol-value list) (lambda (a b)
(string< (car a) (car b))))))
(defun +org-capture-sort-after-init (&optional list)
"Sort LIST with `+org-capture-sort' after Emacs init."
(+ensure-after-init #'+org-capture-sort))
;;;###autoload
(defun +org-capture-templates-setf (key value &optional list sort-after)
"Add KEY to LIST, using `setf'.
LIST is a symbol and defaults to `org-capture-templates' -- so
this function sets values on a list that's structured as such.
Thus, KEY is a string key. If it's longer than one character,
this function will search LIST for each successive run of
characters before the final, ensuring sub-lists exist of the
form (CHARS DESCRIPTION).
For example, if KEY is \"abc\", first a LIST item of the form (a
DESCRIPTION), if non-existant, will be added to the list (with a
default description), then an item of the
form (\"ab\"Â DESCRIPTION), before adding (KEY VALUE) to the LIST.
VALUE is the template or group header required for
`org-capture-templates', which see.
SORT-AFTER, when set to t, will call
`+org-capture-templates-sort' after setting, to ensure org can
properly process the variable."
;; LIST defaults to `org-capture-templates'
(declare (indent 2))
(unless list (setq list 'org-capture-templates))
;; Ensure VALUE is a list to cons properly
(unless (listp value) (setq value (list value)))
(when (> (length key) 1)
;; Check for existence of groups.
(let ((expected (cl-loop for i from 1 to (1- (length key))
collect (substring key 0 i) into keys
finally return keys)))
(cl-loop for ek in expected
if (not (+org-capture--get ek (symbol-value list))) do
(setf (+org-capture--get ek (symbol-value list))
(list (format "(Group %s)" ek))))))
(prog1 ;; Set KEY to VALUE
(setf (+org-capture--get key (symbol-value list)) value)
;; Sort after, maybe
(when sort-after (+org-capture-sort list))))
(defun +org-template--ensure-path (keys &optional list)
"Ensure path of keys exists in `org-capture-templates'."
(unless list (setq list 'org-capture-templates))
(when (> (length key) 1)
;; Check for existence of groups.
(let ((expected (cl-loop for i from 1 to (1- (length key))
collect (substring key 0 i) into keys
finally return keys)))
(cl-loop for ek in expected
if (not (+org-capture--get ek (symbol-value list))) do
(setf (+org-capture--get ek (symbol-value list))
(list (format "(Group %s)" ek)))))))
(defun +org-define-capture-template (keys title &rest args)
)
(provide '+org-capture)
;;; +org-capture.el ends here
|