progfolio / doct

DOCT: Declarative Org Capture Templates for Emacs
GNU General Public License v3.0
375 stars 8 forks source link

Add syntax for adding property drawers to the templates #13

Closed yantar92 closed 4 years ago

yantar92 commented 4 years ago

It would be handy if I could do something like

(doct '("Example"
    :keys "t"
        :file yant/org-inbox-file
    :template
    ("* TODO sample task"
     :properties (("CREATED" . "%U")
                  ":STYLE: habit"
                  ("REPEAT_TO_STATE" . "NEXT")
                  ("LOGGING" . "DONE(!)")
                  ("ARCHIVE" . "%%S_archive_%%y:*Habits")
                  ("ORG-TIME-BONUS-ON-DONE" . "60"))
     "%?")))
progfolio commented 4 years ago

Thanks for the suggestion!

I'm hesitant to add something like this. It's only really applicable when the :type is entry and would complicate the code-base. Fortunately, :template can be a function which constructs the template string.

(let ((org-capture-templates
        (doct
        `("Example" :keys "e"
          :file ""
          :template ,(defun my/doct-with-properties ()
                      "Construct template string from declaration's :head and :properties."
                      (concat (doct-get :head) "\n"
                              (mapconcat (lambda (prop)
                                            (pcase prop
                                              ((pred consp)   (concat ":" (car prop) ": " (cdr prop)))
                                              ((pred stringp) prop)))
                                          (doct-get :properties)
                                          "\n")))
          :head "* TODO sample task"
          :properties (("CREATED" . "%U")
                        ":STYLE: habit"
                        ("REPEAT_TO_STATE" . "NEXT")
                        ("LOGGING" . "DONE(!)")
                        ("ARCHIVE" . "%%S_archive_%%y:*Habits")
                        ("ORG-TIME-BONUS-ON-DONE" . "60"))))))
  (org-capture nil "e"))

I've separated the headline and properties into custom keywords which the function template accesses. You could also specify them together with a single custom keyword and adjust the function to handle that data as you see fit.

yantar92 commented 4 years ago

I'm hesitant to add something like this. It's only really applicable when the :type is entry and would complicate the code-base.

I somehow had an impression that entry :type is one of the most common use-cases of capture templates. Probably, it is just my experience.

Fortunately, :template can be a function which constructs the template string.

Well. I could as well define a macro independently from doct or even add org-capture-before-finalize-hook. Anyway, thanks for showcasing doct-get.

progfolio commented 4 years ago

I agree that it is a common use-case, but the functionality is possible without extending the syntax.

I could as well define a macro independently from doct or even add org-capture-before-finalize-hook.

Sounds more in the realm of a function rather than a macro, unless you had some more complex behavior in mind. You could use a hook as well, but be mindful that the hook will be run multiple times in situations where you're appending to the same heading.

Here's a hook-based example that works with a plist:

(let ((org-capture-templates
       (doct
        `("With Properties" :keys "p"
          :file "/tmp/test.org"
          :template   "* HEADING"
          :properties (:one "two" :three "four")
          :hook ,(defun my/org-property-drawer ()
                   "Add declaration's :properties to current entry."
                   (let ((properties (doct-get :properties)))
                     (dolist (keyword (seq-filter #'keywordp properties))
                       (org-set-property (substring (symbol-name keyword) 1)
                                         (plist-get properties keyword)))))))))
  (org-capture nil "p"))

That function could be defined elsewhere and just referenced by the :hook keyword.

Anyway, thanks for showcasing doct-get.

You're welcome and thanks again for the suggestion.