2

I work with org-mode checkboxes, marking them as completed as I go.

* TODO clean kitchen
- [X] sink
- [ ] stove
- [ ] floors

I want org to move point to the next checkbox when when it gets marked - [X]

I tried this...

(advice-add 'org-toggle-checkbox :after 'org-next-item) 

...which works when I do C-c C-x C-b. But how do I make org-next-item trigger automatically when point is on a checkbox and I do C-c C-c?

2

Juancho's assessment is correct. As it happens, I've been developing some tools for this kind of surgical advice. I think this should do the trick:

(defun my/org-checkbox-toggle-advice (orig-fn &rest args)
  "Advice to move to next list item on checkbox toggle."
  (my/with-advice 
      ((#'org-update-checkbox-count-maybe
        :after (lambda ()
                 (ignore-errors (org-next-item)))))
    (apply orig-fn args)))

(advice-add #'org-ctrl-c-ctrl-c   :around #'my/org-checkbox-toggle-advice)
(advice-add #'org-toggle-checkbox :around #'my/org-checkbox-toggle-advice)

The hard work here is being done by this macro:

(defmacro my/with-advice (adlist &rest body)
  "Execute BODY with temporary advice in ADLIST.

Each element of ADLIST should be a list of the form
  (SYMBOL WHERE FUNCTION [PROPS])
suitable for passing to `advice-add'.  The BODY is wrapped in an
`unwind-protect' form, so the advice will be removed even in the
event of an error or nonlocal exit."
  (declare (debug ((&rest (&rest form)) body))
           (indent 1))
  `(progn
     ,@(mapcar (lambda (adform)
                 (cons 'advice-add adform))
               adlist)
     (unwind-protect (progn ,@body)
       ,@(mapcar (lambda (adform)
                   `(advice-remove ,(car adform) ,(nth 2 adform)))
                 adlist))))
  • Awesome it works! One thing. If point is inside the square brackets on the first checkbox, it works perfectly. However, if point is on the hyphen on the first item and I do <kbd>C-c C-c</kbd>, it checks ALL the boxes then moves me to the next checkbox. – incandescentman Oct 10 '15 at 19:56
  • 1
    I guess my testing wasn't as thorough as I thought it was; nice catch. It looks like I'm screwing up the prefix arg by using funcall instead of apply in my/org-checkbox-toggle-advice. Editing solution now. – Aaron Harris Oct 10 '15 at 20:44
  • Awesome, it works. However, when I do <kbd>C-c C-c</kbd> on the last checkbox to mark my last item as complete, I get Lisp error: (error "On last item") signal(error ("On last item")) error("On last item") org-next-item() apply(org-next-item nil) org-update-checkbox-count-maybe(). – incandescentman Oct 11 '15 at 6:51
  • 1
    After thinking about it a little more, I realized that even if the error just produces a message, it will halt execution of org-ctrl-c-ctrl-c, and I'm not sure that the call to org-update-checkbox-count-maybe will always be the last form to be executed. So it's probably a good idea to trap those errors in any case, and I'm editing the solution to do so. – Aaron Harris Oct 11 '15 at 16:12
  • 1
    I'm guessing you must have changed something recently that changed one of the functions involved, probably either updating Org mode or adding something new to your config. It still works for me, and I'm on Org version 9.0 (and Emacs 25.1.1). – Aaron Harris Jan 3 '17 at 16:23
2

The C-c C-c behaviour on checklists is hard-coded deep inside org-ctrl-c-ctrl-c in file org.el. This is independent from org-toggle-checkbox in file org-list.el. So you'll probably have to modify org-ctrl-c-ctrl-c.

Note that both functions end by calling org-update-checkbox-count-maybe, so you could try advising that function instead. But beware that this last function is also called elsewhere.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.