emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [RFC] DOCT: Declarative Org Capture Templates
@ 2020-04-23 17:30 No Wayman
  2020-04-24 10:01 ` Nicolas Goaziou
  0 siblings, 1 reply; 3+ messages in thread
From: No Wayman @ 2020-04-23 17:30 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 4191 bytes --]

* [RFC] DOCT: Declarative Org Capture Templates

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

https://github.com/progfolio/doct

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

- DOCT validates templates before runtime execution.

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:
- forget about whatever you wanted to capture and press on with 
  your original task
- manually take a note about what you originally wanted to capture 
  and another note to fix the broken template
- drop what you're doing and fix everything
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.

- DOCT makes the parent/child relationship between templates 
  explicit.

`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.

- DOCT manages per-template hooks/contexts.

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.

- DOCT makes adding custom metadata to templates easy.

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:

#+begin_src emacs-lisp
(doct
 `("Note"
   :keys "n"
   :file ,(defun my/project-note-file ()
            (let ((file (expand-file-name "notes.org" (when 
            (functionp 'projectile-project-root)
                                                        (projectile-project-root)))))
              (with-current-buffer (find-file-noselect file)
                (org-mode)
                ;;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))
                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"))))
#+end_src

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.

[-- Attachment #2: Type: text/html, Size: 7074 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC] DOCT: Declarative Org Capture Templates
  2020-04-23 17:30 [RFC] DOCT: Declarative Org Capture Templates No Wayman
@ 2020-04-24 10:01 ` Nicolas Goaziou
  2020-04-24 18:01   ` No Wayman
  0 siblings, 1 reply; 3+ messages in thread
From: Nicolas Goaziou @ 2020-04-24 10:01 UTC (permalink / raw)
  To: No Wayman; +Cc: emacs-orgmode

Hello,

No Wayman <iarchivedmywholelife@gmail.com> writes:

> * [RFC] DOCT: Declarative Org Capture Templates

Thank you for your work. 

I have some comments.

Disclaimer: I am only using very basic capture templates. So, I cannot
comment realistically on the new syntax you suggest. In particular, the
example you give is way too complex for me to understand the benefits of
your syntax. I suggest to start out with showing simple use-cases.

Anyway, I hope more advanced capture template users can chime in and
comment your design.

My beginner questions are the following :

- Is it compatible with the current syntax? If it isn't, is there a way
  to ease transition to the new syntax?

- Is it simple to use on simple use-cases?

- Is it more capable than the current syntax, i.e., does it handle
  situations that are not possible, even in a convoluted way, currently?

> - DOCT validates templates before runtime execution.
>
> 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.

This is different from introducing a new syntax for capture templates.

Actually, `org-insert-place-item' and `org-capture-place-table-line'
both try to fix misshaped templates already. OTOH
`org-capture-place-entry' merely calls `org-capture-verify-tree' on the
template, i.e., it barfs if the template is ill-defined. It is
a discrepancy we could fix independently on your new syntax.

I invite you to propose a patch for `org-capture-place-entry' so it does
a better job at fixing the initial template, if needed. I'll gladly
apply it.


Regards,

-- 
Nicolas Goaziou


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC] DOCT: Declarative Org Capture Templates
  2020-04-24 10:01 ` Nicolas Goaziou
@ 2020-04-24 18:01   ` No Wayman
  0 siblings, 0 replies; 3+ messages in thread
From: No Wayman @ 2020-04-24 18:01 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-orgmode


Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:

> Hello,
>
> No Wayman <iarchivedmywholelife@gmail.com> writes:
>
>> * [RFC] DOCT: Declarative Org Capture Templates
>
> Thank you for your work.

Thank you for taking the time to respond.

> Disclaimer: I am only using very basic capture templates. So, I 
> cannot
> comment realistically on the new syntax you suggest. In 
> particular, the
> example you give is way too complex for me to understand the 
> benefits of
> your syntax. I suggest to start out with showing simple 
> use-cases.

Apologies, it's hard to strike a balance between showing something 
practical and over-writing.

> - Is it compatible with the current syntax? If it isn't, is 
> there a way
>   to ease transition to the new syntax?

My package translates DOCT's syntax into the current syntax.
I have written a separate package that does basic translation from 
the current syntax to DOCT's as well.
It is not optimal yet, but does work for simple cases.
There are a few features of DOCT (property inheritance, management 
of hooks/contexts) that make it more difficult than just a syntax 
swap.
I could come up with something more fully featured, but in my 
experience thus far, it does not take long to translate from one 
syntax to the other manually.

> - Is it simple to use on simple use-cases?

I would say so. There is a single function that does the 
translation. For example:

(doct '("Example" :keys "e" :file ""))

Returns:

(("e" "Example" entry (file "") nil :doct (:doct-name "Example" 
:keys "e" :file "")))

Part of my frustration of writing templates was always having to 
look up the structure of the template list.
Keys, description, type, target (with its variations) and 
template-string (with its variations) is a lot to remember.

Whereas, with:

(doct '("Example" :keys "e" :file ""))

I need only remember that the description comes first. The 
keywords are more self-describing as well.
There's an inherent complexity to the flexibility that org-capture 
offers, but this makes templates easier to write/read.

> - Is it more capable than the current syntax, i.e., does it 
> handle
>   situations that are not possible, even in a convoluted way, 
>   currently?

>> - DOCT validates templates before runtime execution.
>>
>> 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.
>
> This is different from introducing a new syntax for capture 
> templates.
>
> Actually, `org-insert-place-item' and 
> `org-capture-place-table-line'
> both try to fix misshaped templates already. OTOH
> `org-capture-place-entry' merely calls `org-capture-verify-tree' 
> on the
> template, i.e., it barfs if the template is ill-defined. It is
> a discrepancy we could fix independently on your new syntax.
>
> I invite you to propose a patch for `org-capture-place-entry' so 
> it does
> a better job at fixing the initial template, if needed. I'll 
> gladly
> apply it.

`org-capture-place-entry' is run after `org-capture' is invoked, 
so while I agree a patch could improve the error, the user still 
hits that error when they are using their capture template 
(defeating the point of org-capture letting you take a quick note 
without losing your current context).
DOCT checks while converting declarations to templates, so the 
error is thrown before org-capture is used (almost like linting 
for templates).

Aside from that, most of what DOCT does is sugar for common use 
patterns I've observed in others' org-capture-templates.
For example, adding per-declaration hooks:

Without DOCT:

;;rest of template configured elsewhere...
;;make sure you update this if you ever change the key for this 
  template!
(defun my-org-template-hook ()
  (when (string= (org-capture-get :key t) "t")
    (message "Template \"t\" selected.")))

(add-hook 'org-capture-mode-hook 'my-org-template-hook)

With DOCT:

(doct `("Example" :keys "t" :file ""
        :hook (lambda () (message "Template %s selected." 
        (doct-get :keys)))))

DOCT ensures that function is only run for that template without 
having the user manually filter against `org-capture-plist's :key.
It also allows the user to do this inline with the rest of the 
declaration vs spreading it out.


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-04-24 18:01 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-23 17:30 [RFC] DOCT: Declarative Org Capture Templates No Wayman
2020-04-24 10:01 ` Nicolas Goaziou
2020-04-24 18:01   ` No Wayman

Code repositories for project(s) associated with this inbox:

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).