[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC] DOCT: Declarative Org Capture Templates

From: No Wayman
Subject: [RFC] DOCT: Declarative Org Capture Templates
Date: Thu, 23 Apr 2020 13:30:25 -0400
User-agent: mu4e 1.3.10; emacs 28.0.50

I've been working on an alternative syntax for org-capture-templates. The result is a package called "DOCT" (declarative org capture templates):


A brief list of what I believe to be improvements over the current syntax/implementation:

For exmaple, you have a template with an entry type of `'entry' and you forget the leading star in the template string. Days later you go to use that template. It's borked. You have a number of options:

None of these are ideal and all of them result in distraction. DOCT performs a number of checks ahead of time when possible to prevent these types of errors.

`org-capture-templates` is a flat list. The relationship between templates is hardcoded in each template's "keys" value. If you want to change the key for a top-level menu, you must then change it in each descendant's keys. DOCT uses nested plists and implements property inheritance.

Currently if you want to have a hook run for a particular template, you have to filter against `org-capture-plist' to check for the appropriate :key value. As stated above, this is fragile and you have to update that key value in numerous places if it ever changes. The same goes for `org-capture-templates-contexts`. DOCT allows specifying per-template contexts and hooks with the rest of the template's configuration.

A common pattern for attaching data to a template is to add to `org-capture-plist'. This pollutes `org-capture-plist' more than necessary. DOCT adds custom data to `org-capture-plist' under a single :doct keyword and allows users to access that data in the template string with familiar %-escape syntax.

This example is one I use daily for taking notes in programming projects:

   :keys "n"
   :file ,(defun my/project-note-file ()
            (let ((file (expand-file-name "notes.org" (when (functionp 'projectile-project-root)
              (with-current-buffer (find-file-noselect file)
                ;;set to utf-8 because we may be visiting raw file
                (setq buffer-file-coding-system 'utf-8-unix)
                (when-let ((headline (doct-get :headline)))
                  (unless (org-find-exact-headline-in-buffer headline)
                    (goto-char (point-max))
                    (insert "* " headline)
                    (org-set-tags (downcase headline))))
                (unless (file-exists-p file) (write-file file))
   :template (lambda () (concat  "* %{todo-state} " (when (y-or-n-p "link?") "%A\n") "%?"))
   :todo-state "TODO"
   :children (("bug"           :keys "b" :headline "Bugs")
              ("documentation" :keys "d" :headline "Documentation")
              ("enhancement"   :keys "e" :headline "Enhancements" :todo-state "IDEA")
              ("feature"       :keys "f" :headline "Features"     :todo-state "IDEA")
              ("optimization"  :keys "o" :headline "Optimizations")
              ("miscellaneous" :keys "m" :headline "Miscellaneous")
              ("security"      :keys "s" :headline "Security"))))

Each template inherits its parent's file finding function,template string, and a default :todo-state. The template string access the child's :todo-state keyword with the "%{KEYWORD}" syntax in the template string.

I would be happy to work on getting these features into Org if there is any interest. Any feedback is welcome.

Thanks, nv.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]