Function: org-toggle-checkbox

org-toggle-checkbox is an interactive and byte-compiled function defined in org-list.el.gz.

Signature

(org-toggle-checkbox &optional TOGGLE-PRESENCE)

Documentation

Toggle the checkbox in the current line.

With prefix argument TOGGLE-PRESENCE, add or remove checkboxes. With a double prefix argument, set the checkbox to "[-]".

When there is an active region, toggle status or presence of the first checkbox there, and make every item inside have the same status or presence, respectively.

If point is on a headline, apply this to all checkbox items in the text below the heading, taking as reference the first item in subtree, ignoring planning line and any drawer following it.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-list.el.gz
(defun org-toggle-checkbox (&optional toggle-presence)
  "Toggle the checkbox in the current line.

With prefix argument TOGGLE-PRESENCE, add or remove checkboxes.
With a double prefix argument, set the checkbox to \"[-]\".

When there is an active region, toggle status or presence of the
first checkbox there, and make every item inside have the same
status or presence, respectively.

If point is on a headline, apply this to all checkbox items in
the text below the heading, taking as reference the first item in
subtree, ignoring planning line and any drawer following it."
  (interactive "P")
  (if (org-at-radio-list-p)
      (org-toggle-radio-button toggle-presence)
    (save-excursion
      (let* (singlep
	     block-item
	     lim-up
	     lim-down
	     (orderedp (org-entry-get nil "ORDERED"))
	     (_bounds
	      ;; In a region, start at first item in region.
	      (cond
	       ((org-region-active-p)
		(let ((limit (region-end)))
		  (goto-char (region-beginning))
		  (if (org-list-search-forward (org-item-beginning-re) limit t)
                      (setq lim-up (line-beginning-position))
		    (error "No item in region"))
		  (setq lim-down (copy-marker limit))))
	       ((org-at-heading-p)
		;; On a heading, start at first item after drawers and
		;; timestamps (scheduled, etc.).
		(let ((limit (save-excursion (outline-next-heading) (point))))
		  (org-end-of-meta-data t)
		  (if (org-list-search-forward (org-item-beginning-re) limit t)
                      (setq lim-up (line-beginning-position))
		    (error "No item in subtree"))
		  (setq lim-down (copy-marker limit))))
	       ;; Just one item: set SINGLEP flag.
	       ((org-at-item-p)
		(setq singlep t)
                (setq lim-up (line-beginning-position)
                      lim-down (copy-marker (line-end-position))))
	       (t (error "Not at an item or heading, and no active region"))))
	     ;; Determine the checkbox going to be applied to all items
	     ;; within bounds.
	     (ref-checkbox
	      (progn
		(goto-char lim-up)
		(let ((cbox (and (org-at-item-checkbox-p) (match-string 1))))
		  (cond
		   ((equal toggle-presence '(16)) "[-]")
		   ((equal toggle-presence '(4))
		    (unless cbox "[ ]"))
		   ((equal "[X]" cbox) "[ ]")
		   (t "[X]"))))))
	;; When an item is found within bounds, grab the full list at
	;; point structure, then: (1) set check-box of all its items
	;; within bounds to REF-CHECKBOX, (2) fix check-boxes of the
	;; whole list, (3) move point after the list.
	(goto-char lim-up)
	(while (and (< (point) lim-down)
		    (org-list-search-forward (org-item-beginning-re)
					     lim-down 'move))
	  (let* ((struct (org-list-struct))
		 (struct-copy (copy-tree struct))
		 (parents (org-list-parents-alist struct))
		 (prevs (org-list-prevs-alist struct))
		 (bottom (copy-marker (org-list-get-bottom-point struct)))
		 (items-to-toggle (cl-remove-if
				   (lambda (e) (or (< e lim-up) (> e lim-down)))
				   (mapcar #'car struct))))
	    (dolist (e items-to-toggle)
	      (org-list-set-checkbox
	       e struct
	       ;; If there is no box at item, leave as-is unless
	       ;; function was called with C-u prefix.
	       (let ((cur-box (org-list-get-checkbox e struct)))
		 (if (or cur-box (equal toggle-presence '(4)))
		     ref-checkbox
		   cur-box))))
	    (setq block-item (org-list-struct-fix-box
			      struct parents prevs orderedp))
	    ;; Report some problems due to ORDERED status of subtree.
	    ;; If only one box was being checked, throw an error, else,
	    ;; only signal problems.
	    (cond
	     ((and singlep block-item (> lim-up block-item))
	      (error
	       "Checkbox blocked because of unchecked box at line %d"
	       (org-current-line block-item)))
	     (block-item
	      (message
	       "Checkboxes were removed due to unchecked box at line %d"
	       (org-current-line block-item))))
	    (goto-char bottom)
	    (move-marker bottom nil)
	    (org-list-struct-apply-struct struct struct-copy)))
	(move-marker lim-down nil))))
  (org-update-checkbox-count-maybe))