My brain works in two non-standard org ways: - I don't like having the =CLOSED= timestamp outside of property drawers, and - no =todo= tag (or a =todo= tag of "" if you like) is still a =todo= tag and often means =DONE=.
So standard state change logging doesn't work for me. All I really want to track, though, is the timestamp of the latest state change. Hence: #+begin_src emacs-lisp (defun my/log-state-change () "logs timestamps in PROPERTIES for any todo-tag state change (LAST). " (interactive) (save-excursion (let* ((stamp (org-string-timestamp nil t t nil nil nil))) (org-set-property "LAST" (concatenate 'string org-state " " stamp))))) #+end_src #+begin_src emacs-lisp (add-hook 'org-after-todo-state-change-hook 'my/log-state-change) #+end_src This works fine except for the following conditions: - the =todo= tag is changing to a non-nil value, - there is not (yet) any heading, - point is exactly at the start of the header (after stars and =todo= tag if any), and - there is no properties drawer yet. In this case, point moves from the header to after the properties drawer. A few examples showing intention and bug (representing point by ^): Example 1: works - before shift-right #+begin_example * ^test #+end_example - after shift-right #+begin_example * TODO ^test :PROPERTIES: :OPEN: [2012-08-22 Wed 15:51] :LAST: TODO [2012-08-22 Wed 15:51] :END: #+end_example Example 2: buggy - point shifts - before shift-right #+begin_example * ^ #+end_example - after shift-right #+begin_example * TODO :PROPERTIES: :LAST: TODO [2012-08-22 Wed 15:51] :END:^ #+end_example Example 3: ok - before shift-right #+begin_example ^* #+end_example - after shift-right #+begin_example * TODO ^ :PROPERTIES: :LAST: TODO [2012-08-22 Wed 15:51] :END: #+end_example Example 4: strangely, this works (standard TODO -> DONE -> "" cycle) - before shift-right #+begin_example * DONE ^ #+end_example - after shift-right #+begin_example * ^ :PROPERTIES: :LAST: [2012-08-22 Wed 15:51] :END: #+end_example Any ideas? How can point change if you have a save-excursion in place? My main thought was that the properties drawer is being inserted before point but /only when/ there is no heading. I've spent some time squinting at org-entry-put to check this, but debugging let alone understanding org-with-point-at is way beyond me.