diff --git a/lisp/org-list.el b/lisp/org-list.el index 6d25037a8..415986e55 100644 --- a/lisp/org-list.el +++ b/lisp/org-list.el @@ -1914,16 +1914,21 @@ Initial position of cursor is restored after the changes." (goto-char origin) (move-marker origin nil))) -(defun org-list-write-struct (struct parents) +(defun org-list-write-struct (struct parents &optional old-struct) "Correct bullets, checkboxes and indentation in list at point. + STRUCT is the list structure. PARENTS is the alist of parents, -as returned by `org-list-parents-alist'." +as returned by `org-list-parents-alist'. + +When non-nil, optional argument OLD-STRUCT is the reference +structure of the list. It should be provided whenever STRUCT +doesn't correspond anymore to the real list in buffer." ;; Order of functions matters here: checkboxes and endings need ;; correct indentation to be set, and indentation needs correct ;; bullets. ;; ;; 0. Save a copy of structure before modifications - (let ((old-struct (copy-tree struct))) + (let ((old-struct (or old-struct (copy-tree struct)))) ;; 1. Set a temporary, but coherent with PARENTS, indentation in ;; order to get items endings and bullets properly (org-list-struct-fix-ind struct parents 2) diff --git a/lisp/org.el b/lisp/org.el index 11709324f..5397e262a 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -18390,12 +18390,19 @@ This command does many different things, depending on context: block-item) ;; Use a light version of `org-toggle-checkbox' to avoid ;; computing list structure twice. - (org-list-set-checkbox (point-at-bol) struct - (cond - ((equal arg '(16)) "[-]") - ((equal arg '(4)) nil) - ((equal "[X]" cbox) "[ ]") - (t "[X]"))) + (let ((new-box (cond + ((equal arg '(16)) "[-]") + ((equal arg '(4)) nil) + ((equal "[X]" cbox) "[ ]") + (t "[X]")))) + (if firstp + ;; If at first item of sub-list, remove check-box from + ;; every item at the same level. + (mapc + (lambda (pos) (org-list-set-checkbox pos struct new-box)) + (org-list-get-all-items + (point-at-bol) struct (org-list-prevs-alist struct))) + (org-list-set-checkbox (point-at-bol) struct new-box))) ;; Replicate `org-list-write-struct', while grabbing a return ;; value from `org-list-struct-fix-box'. (org-list-struct-fix-ind struct parents 2) @@ -18417,9 +18424,20 @@ This command does many different things, depending on context: ;; only if function was called with an argument. Send list only ;; if at top item. (let* ((struct (org-list-struct)) + (new-struct struct) (firstp (= (org-list-get-top-point struct) (point-at-bol)))) - (when arg (org-list-set-checkbox (point-at-bol) struct "[ ]")) - (org-list-write-struct struct (org-list-parents-alist struct)) + (when arg + (setq new-struct (copy-tree struct)) + (if firstp + ;; If at first item of sub-list, add check-box to every + ;; item at the same level. + (mapc + (lambda (pos) (org-list-set-checkbox pos new-struct "[ ]")) + (org-list-get-all-items + (point-at-bol) new-struct (org-list-prevs-alist new-struct))) + (org-list-set-checkbox (point-at-bol) new-struct "[ ]"))) + (org-list-write-struct + new-struct (org-list-parents-alist new-struct) struct) (when arg (org-update-checkbox-count-maybe)) (when firstp (org-list-send-list 'maybe)))) ((save-excursion (beginning-of-line 1) (looking-at org-dblock-start-re))