lang/org: add centralized org-capture project targets
For saving project todos/notes/changelogs in a central {org-directory}/projects.org file, under {Project Name}/{Tasks,Notes,Changelog} headings. If you want to prefix the outline path, you can specific a :parents property. e.g. (after! org-capture (org-capture-put :parents '("Projects"))) or (dolist (key '("ot" "on" "oc")) (setf (alist-get key org-capture-templates) (append (alist-get key org-capture-templates) '(:parents ("Projects"))))) Also sets :kill-buffer t by default, for all org capture templates.
This commit is contained in:
parent
fd00870ae8
commit
040fcfcffa
2 changed files with 95 additions and 20 deletions
|
@ -76,15 +76,6 @@ you're done. This can be called from an external shell script."
|
||||||
;;
|
;;
|
||||||
;;; Capture targets
|
;;; Capture targets
|
||||||
|
|
||||||
(defun +org--capture-root (path)
|
|
||||||
(let ((filename (file-name-nondirectory path)))
|
|
||||||
(expand-file-name
|
|
||||||
filename
|
|
||||||
(or (locate-dominating-file (file-truename default-directory)
|
|
||||||
filename)
|
|
||||||
(doom-project-root)
|
|
||||||
(user-error "Couldn't detect a project")))))
|
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +org-capture-todo-file ()
|
(defun +org-capture-todo-file ()
|
||||||
"Expand `+org-capture-todo-file' from `org-directory'.
|
"Expand `+org-capture-todo-file' from `org-directory'.
|
||||||
|
@ -97,21 +88,77 @@ If it is an absolute path return `+org-capture-todo-file' verbatim."
|
||||||
If it is an absolute path return `+org-capture-todo-file' verbatim."
|
If it is an absolute path return `+org-capture-todo-file' verbatim."
|
||||||
(expand-file-name +org-capture-notes-file org-directory))
|
(expand-file-name +org-capture-notes-file org-directory))
|
||||||
|
|
||||||
|
(defun +org--capture-local-root (path)
|
||||||
|
(let ((filename (file-name-nondirectory path)))
|
||||||
|
(expand-file-name
|
||||||
|
filename
|
||||||
|
(or (locate-dominating-file (file-truename default-directory)
|
||||||
|
filename)
|
||||||
|
(doom-project-root)
|
||||||
|
(user-error "Couldn't detect a project")))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +org-capture-project-todo-file ()
|
(defun +org-capture-project-todo-file ()
|
||||||
"Find the nearest `+org-capture-todo-file' in a parent directory, otherwise,
|
"Find the nearest `+org-capture-todo-file' in a parent directory, otherwise,
|
||||||
opens a blank one at the project root. Throws an error if not in a project."
|
opens a blank one at the project root. Throws an error if not in a project."
|
||||||
(+org--capture-root +org-capture-todo-file))
|
(+org--capture-local-root +org-capture-todo-file))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +org-capture-project-notes-file ()
|
(defun +org-capture-project-notes-file ()
|
||||||
"Find the nearest `+org-capture-notes-file' in a parent directory, otherwise,
|
"Find the nearest `+org-capture-notes-file' in a parent directory, otherwise,
|
||||||
opens a blank one at the project root. Throws an error if not in a project."
|
opens a blank one at the project root. Throws an error if not in a project."
|
||||||
(+org--capture-root +org-capture-notes-file))
|
(+org--capture-local-root +org-capture-notes-file))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +org-capture-project-changelog-file ()
|
(defun +org-capture-project-changelog-file ()
|
||||||
"Find the nearest `+org-capture-changelog-file' in a parent directory,
|
"Find the nearest `+org-capture-changelog-file' in a parent directory,
|
||||||
otherwise, opens a blank one at the project root. Throws an error if not in a
|
otherwise, opens a blank one at the project root. Throws an error if not in a
|
||||||
project."
|
project."
|
||||||
(+org--capture-root +org-capture-changelog-file))
|
(+org--capture-local-root +org-capture-changelog-file))
|
||||||
|
|
||||||
|
(defun +org--capture-ensure-heading (headings &optional initial-level)
|
||||||
|
(if (not headings)
|
||||||
|
(widen)
|
||||||
|
(let ((initial-level (or initial-level 1)))
|
||||||
|
(if (and (re-search-forward (format org-complex-heading-regexp-format
|
||||||
|
(regexp-quote (car headings)))
|
||||||
|
nil t)
|
||||||
|
(= (org-current-level) initial-level))
|
||||||
|
(progn
|
||||||
|
(beginning-of-line)
|
||||||
|
(org-narrow-to-subtree))
|
||||||
|
(goto-char (point-max))
|
||||||
|
(unless (and (bolp) (eolp)) (insert "\n"))
|
||||||
|
(insert (make-string initial-level ?*)
|
||||||
|
" " (car headings) "\n")
|
||||||
|
(beginning-of-line 0))
|
||||||
|
(+org--capture-ensure-heading (cdr headings) (1+ initial-level)))))
|
||||||
|
|
||||||
|
(defun +org--capture-central-file (file project)
|
||||||
|
(let ((file (expand-file-name +org-capture-projects-file org-directory)))
|
||||||
|
(set-buffer (org-capture-target-buffer file))
|
||||||
|
(org-capture-put-target-region-and-position)
|
||||||
|
(widen)
|
||||||
|
(goto-char (point-min))
|
||||||
|
;; Find or create the project headling
|
||||||
|
(+org--capture-ensure-heading
|
||||||
|
(append (org-capture-get :parents)
|
||||||
|
(list project (org-capture-get :heading))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun +org-capture-central-project-todo-file ()
|
||||||
|
"TODO"
|
||||||
|
(+org--capture-central-file
|
||||||
|
+org-capture-todo-file (projectile-project-name)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun +org-capture-central-project-notes-file ()
|
||||||
|
"TODO"
|
||||||
|
(+org--capture-central-file
|
||||||
|
+org-capture-notes-file (projectile-project-name)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun +org-capture-central-project-changelog-file ()
|
||||||
|
"TODO"
|
||||||
|
(+org--capture-central-file
|
||||||
|
+org-capture-changelog-file (projectile-project-name)))
|
||||||
|
|
|
@ -39,6 +39,9 @@ target file.
|
||||||
Is relative to `org-directory', unless it is absolute. Is used in Doom's default
|
Is relative to `org-directory', unless it is absolute. Is used in Doom's default
|
||||||
`org-capture-templates'.")
|
`org-capture-templates'.")
|
||||||
|
|
||||||
|
(defvar +org-capture-projects-file "projects.org"
|
||||||
|
"Default, centralized target for org-capture templates.")
|
||||||
|
|
||||||
(defvar +org-initial-fold-level 2
|
(defvar +org-initial-fold-level 2
|
||||||
"The initial fold level of org files when no #+STARTUP options for it.")
|
"The initial fold level of org files when no #+STARTUP options for it.")
|
||||||
|
|
||||||
|
@ -241,25 +244,50 @@ I like:
|
||||||
org-capture-templates
|
org-capture-templates
|
||||||
'(("t" "Personal todo" entry
|
'(("t" "Personal todo" entry
|
||||||
(file+headline +org-capture-todo-file "Inbox")
|
(file+headline +org-capture-todo-file "Inbox")
|
||||||
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)
|
"* TODO %?\n%i\n%a" :prepend t)
|
||||||
("n" "Personal notes" entry
|
("n" "Personal notes" entry
|
||||||
(file+headline +org-capture-notes-file "Inbox")
|
(file+headline +org-capture-notes-file "Inbox")
|
||||||
"* %u %?\n%i\n%a" :prepend t :kill-buffer t)
|
"* %u %?\n%i\n%a" :prepend t)
|
||||||
|
|
||||||
;; Will use {project-root}/{todo,notes,changelog}.org, unless a
|
;; Will use {project-root}/{todo,notes,changelog}.org, unless a
|
||||||
;; {todo,notes,changelog}.org file is found in a parent directory.
|
;; {todo,notes,changelog}.org file is found in a parent directory.
|
||||||
;; Uses the basename from `+org-capture-todo-file',
|
;; Uses the basename from `+org-capture-todo-file',
|
||||||
;; `+org-capture-changelog-file' and `+org-capture-notes-file'.
|
;; `+org-capture-changelog-file' and `+org-capture-notes-file'.
|
||||||
("p" "Templates for projects")
|
("p" "Templates for projects")
|
||||||
("pt" "Project todo" entry ; {project-root}/todo.org
|
("pt" "Project-local todo" entry ; {project-root}/todo.org
|
||||||
(file+headline +org-capture-project-todo-file "Inbox")
|
(file+headline +org-capture-project-todo-file "Inbox")
|
||||||
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)
|
"* TODO %?\n%i\n%a" :prepend t)
|
||||||
("pn" "Project notes" entry ; {project-root}/notes.org
|
("pn" "Project-local notes" entry ; {project-root}/notes.org
|
||||||
(file+headline +org-capture-project-notes-file "Inbox")
|
(file+headline +org-capture-project-notes-file "Inbox")
|
||||||
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)
|
"* %?\n%i\n%a" :prepend t)
|
||||||
("pc" "Project changelog" entry ; {project-root}/changelog.org
|
("pc" "Project-local changelog" entry ; {project-root}/changelog.org
|
||||||
(file+headline +org-capture-project-changelog-file "Unreleased")
|
(file+headline +org-capture-project-changelog-file "Unreleased")
|
||||||
"* TODO %?\n%i\n%a" :prepend t :kill-buffer t)))
|
"* %?\n%i\n%a" :prepend t)
|
||||||
|
|
||||||
|
;; Will use {org-directory}/{+org-capture-projects-file} and store
|
||||||
|
;; these under {ProjectName}/{Tasks,Notes,Changelog} headings. They
|
||||||
|
;; support `:parents' to specify what headings to put them under, e.g.
|
||||||
|
;; :parents ("Projects")
|
||||||
|
("o" "Centralized templates for projects")
|
||||||
|
("ot" "Project todo" entry
|
||||||
|
(function +org-capture-central-project-todo-file)
|
||||||
|
"* TODO %?\n %i\n %a"
|
||||||
|
:heading "Tasks"
|
||||||
|
:prepend nil)
|
||||||
|
("on" "Project notes" entry
|
||||||
|
(function +org-capture-central-project-notes-file)
|
||||||
|
"* %?\n %i\n %a"
|
||||||
|
:heading "Notes"
|
||||||
|
:prepend t)
|
||||||
|
("oc" "Project changelog" entry
|
||||||
|
(function +org-capture-central-project-changelog-file)
|
||||||
|
"* %?\n %i\n %a"
|
||||||
|
:heading "Changelog"
|
||||||
|
:prepend t)))
|
||||||
|
|
||||||
|
;; Kill capture buffers by default (unless they've been visited)
|
||||||
|
(after! org-capture
|
||||||
|
(org-capture-put :kill-buffer t))
|
||||||
|
|
||||||
(defadvice! +org--capture-expand-variable-file-a (file)
|
(defadvice! +org--capture-expand-variable-file-a (file)
|
||||||
"If a variable is used for a file path in `org-capture-template', it is used
|
"If a variable is used for a file path in `org-capture-template', it is used
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue