#org-mode answers: task creation time, subtree at end, Emacs Lisp variables in TBLFM, logbook and refile

Posted: - Modified: | emacs, org

In the interest of getting more tips out there so that they can be searchable, here are a few things I helped people out with on the #org-mode channel on freenode.net and through e-mail.

How can I log task creation times in Org Mode?

You can use an Org capture template.

How can I create a subtree at the end of the current entry?

C-u C-u C-RET M-right gets you the behaviour without configuration, or you can use:

(defun my/org-insert-subheading-after () (interactive) (org-insert-subheading '(16)))

and bind it to a speed command or a shortcut.

How can I refer to Emacs Lisp variables in #+TBLFM?

#+TBLFM: @1$2='(+ @1$1 my-var1);L

How can I write a command that adds a logbook entry and refiles a subtree?

Here was the source that someone asked me for help on:

#+TODO: TODO(t!) | DONE(d!)
#+NAME: startup
#+BEGIN_SRC emacs-lisp
(setq org-log-into-drawer t)
(setq org-use-speed-commands t)
(defun my/refiletree (file headline &optional arg)
               (let ((pos (save-excursion
                      (find-file file)
                      (org-find-exact-headline-in-buffer headline))))
               (org-refile arg nil (list headline file nil pos)))
               (switch-to-buffer (current-buffer)))

;;(setq org-use-speed-commands 'my/org-use-speed-commands-for-headings-and-lists)

(add-to-list 'org-speed-commands-user '("t" (lambda ()
                                               (org-todo "TODO")
                                               (my/refiletree buffer-file-name "Next"))))
(add-to-list 'org-speed-commands-user '("d" (lambda ()
                                               (org-todo "DONE")
                                               (my/refiletree buffer-file-name "Done"))))
#+END_SRC

* Inbox
** Task 1
** Task 2
** Task 3
* Next
* Done

The problem was that the logbook entry was getting added to the wrong heading, since the subtree had already been refiled. It's because logging is done in post-command-hook (example code from org-add-log-setup: (add-hook 'post-command-hook 'org-add-log-note 'append)). That's why it gets confused. Try this. It defines a function to add to org-after-refile-insert-hook.

(setq org-log-into-drawer t)
(setq org-use-speed-commands t)
(defmacro my/def-state-and-refile-shortcut (key state heading)
  `(progn
     (defun ,(intern (concat "my/change-state-to-" state)) ()
       (org-todo ,state)
       (remove-hook 'org-after-refile-insert-hook (quote ,(intern (concat "my/change-state-to-" state)))))
     (add-to-list 'org-speed-commands-user
                  '(,key
                    (lambda ()
                      (add-hook 'org-after-refile-insert-hook (quote ,(intern (concat "my/change-state-to-" state))))
                      (my/refiletree buffer-file-name ,heading))))))
(my/def-state-and-refile-shortcut "t" "TODO" "Next")
(my/def-state-and-refile-shortcut "d" "DONE" "Done")
(defun my/refiletree (file headline &optional arg)
  (let ((pos (with-current-buffer (or (find-buffer-visiting file)
                                      (find-file-noselect file))
               (save-excursion
                 (org-find-exact-headline-in-buffer headline)))))
    (org-refile nil nil (list headline file nil pos))))
You can comment with Disqus or you can e-mail me at sacha@sachachua.com.