contrun / dotfiles

5 stars 2 forks source link

Org capture templates: file+olp+datetree #1

Closed progfolio closed 4 years ago

progfolio commented 4 years ago

I've been looking for examples of people using doct in the wild and I came across your dotfiles! I see you have it installed, but haven't converted your capture templates yet. I'd be happy to show you how I'd organize them if you're interested.

Also, I had a quick question regarding your templates. I noticed you have several templates where the target is (file+olp+datetree ...), but you do not provide an outline path:

https://github.com/contrun/dotfiles/blob/667d27ad0057907ee2199798fdffaba0b8d62ebf/emacs/.emacs.d/config.el#L2794-L2803

Do these actually work for you? When you capture using the templates is the datetree created in the target file? It seems to me like this would fail when trying to capture, because org-capture will not find the headline with a nil olp.

contrun commented 4 years ago

Thank you for your excellent package. I really love the idea. I didn't try it because it requires some time. I just tried it. I can not replicate my current behavior for file+olp+datetree.

With the following minimal configuration

(setq org-capture-templates
      '(("j" "journal" entry (file+olp+datetree "/tmp/t.org")
         "* %?%:description\nEntered on %U\n  %:initial\n  %a\n"
         )))

If I press j, org will create a tree like this

* 2020
** 2020-02 February
*** 2020-02-21 Friday
**** test of a journal title
   Entered on [2020-02-21 Fri 20:00]
**** Just a simple test
   Entered on [2020-02-21 Fri 20:51]

     [[file:~/.files/open/emacs/.emacs.d/config.el::))]]

The heading test of a journal title and Just a simple test are typed in by myself, while the parent headings are generated automatically by org.

I tried the following config

(setq org-capture-templates
      (doct
       `(("journal"
          :keys "j"
          :file "/tmp/t.org"
          :olp ("")
          :datetree t
          :template ("* %?%:description"
                     "Entered on %U"
                     "  %:initial"
                     "  %a")
          )
         )
       )
      )

then I got org-find-olp: Heading not found on level 1:, while the the following configuration

(setq org-capture-templates
      (doct
       `(("journal"
          :keys "j"
          :file "/tmp/t.org"
          :datetree t
          :template ("* %?%:description"
                     "Entered on %U"
                     "  %:initial"
                     "  %a")
          )
         )
       )
      )

generates

* 2020
** 2020-02 February
*** 2020-02-21 Friday
* another test
Entered on [2020-02-21 Fri 20:58]

  [[file:~/.files/open/emacs/.emacs.d/config.el::)]]

Note the heading level is not right on this configuration.

progfolio commented 4 years ago

Pushed a fix that should allow you to use :file :datetree without specifying an :olp. I've tested it with a modified version of your example and it seems to work for me:

(let ((org-capture-templates
       (doct
        `(("journal"
           :keys "j"
           :file "/tmp/t.org"
           :datetree t
           :template ("* %?%:description"
                      "Entered on %U"
                      "  %:initial"
                      "  %a"))))))
  (org-capture nil "j"))

Let me know if that works for you!

contrun commented 4 years ago

Thank you for your efforts. It's now working great. Just one more thing.

Currently the following template automatically creates a org file based on the typed in title. I am unable to do this with doct.

(defun my/generate-org-quick-note-name ()
  "Generate hakyll file name."
  (setq my-org-note--title (read-string "Title: "))
  (setq my-org-note--title-slugified (my/slugify my-org-note--title))
  (setq my-org-note--date (format-time-string "%Y-%m-%d"))
  ;; rfc 5322 style time format, shell command: date -R
  (setq my-org-note--time (let ((system-time-locale "en_US.UTF-8"))
                            (format-time-string "%a, %d %b %Y %H:%M:%S %z")
                            ))
  (expand-file-name (format "%s-%s.org" my-org-note--date my-org-note--title-slugified) "/tmp"))

(setq org-capture-templates
      `(("q" "quick"
         plain (file my/generate-org-quick-note-name)
         "%(format \"#+TITLE: %s\n#+DATE: %s\n#+SLUG: %s\n\n\" my-org-note--title my-org-note--time my-org-note--title-slugified)%?")
        ))

I gave it a shot on

(setq org-capture-templates
      (doct
       `(("quick"
          :keys "q"
          :type plain
          :function (lambda() (my/generate-org-quick-note-name))
          :template ("%(format \"#+TITLE: %s\" my-org-note--title)"
                     "%(format \"#+DATE: %s\" my-org-note--time)"
                     "%(format \"#+SLUG: %s\" my-org-note--title-slugified)"
                     ""
                     "%?")))))

This didn't work. Org-mode didn't actually create a new file. It seems that the return value of my/generate-org-quick-note-name is not passed to org-mode.

progfolio commented 4 years ago

I believe that's because you're using the :function keyword, which translates to the vanilla syntax of:

(function my/function)

In that case, your function would have to create the file if it did not exist, then visit it and move point to your desired location for inserting the template.

However, :file can take a function as its value and should create the file for you if it does not exist. Try substituting :function for :file like so:

(setq org-capture-templates
      (doct
       `(("quick"
          :keys "q"
          :type plain
          :file (lambda() (my/generate-org-quick-note-name))
          :template ("%(format \"#+TITLE: %s\" my-org-note--title)"
                     "%(format \"#+DATE: %s\" my-org-note--time)"
                     "%(format \"#+SLUG: %s\" my-org-note--title-slugified)"
                     ""
                     "%?")))))

Let me know if that works for you.

progfolio commented 4 years ago

I'm also working on a patch now so you don't have to wrap your function symbol in a lambda. e.g.

:file (lambda () (my/generate-org-quick-note-name))

Will just become:

:file my/generate-org-quick-note-name
progfolio commented 4 years ago

Patch is merged into master.

(setq org-capture-templates
      (doct
       `(("quick"
          :keys "q"
          :type plain
          :file my/generate-org-quick-note-name
          :template ("%(format \"#+TITLE: %s\" my-org-note--title)"
                     "%(format \"#+DATE: %s\" my-org-note--time)"
                     "%(format \"#+SLUG: %s\" my-org-note--title-slugified)"
                     ""
                     "%?")))))

Should work now. I've added warnings for cases when the :file or :function value is an unbounded symbol during conversion. These can be controlled globally via the doct-warn-when-unbound custom option or on a per-declaration basis by setting the :doct-warn property.

I really appreciate you taking the time to test this out. Your help has made doct a better package. Thanks again and if you run into any issues, please let me know.

contrun commented 4 years ago

I just tried it. It works like a charm. I really appreciate your quick response, and you made my day. Thank you. I am closing this issue.