org-list: small optimization for cookies updating

* lisp/org-list.el (org-update-checkbox-count): do not recompute every
  list before next heading when there are more than one cookie in an
  headline. Moreover, ignore the case where cookie is inserted neither
  at an heading nor at an item.
This commit is contained in:
Nicolas Goaziou 2011-01-05 00:04:11 +01:00
parent 2621fe0461
commit 39d85b5e39
1 changed files with 57 additions and 43 deletions

View File

@ -2186,55 +2186,69 @@ With optional prefix argument ALL, do this for the whole buffer."
(setq c-all (+ (length cookies) c-all)
c-on (+ (org-count "[X]" cookies) c-on))))
structs))))
cookies-list backup-end structs-backup)
(backup-end 1)
cookies-list structs-backup)
(goto-char (car bounds))
;; 1. Build an alist for each cookie found within BOUNDS. The
;; key will be position at beginning of cookie and values
;; ending position, format of cookie, number of checked boxes
;; to report, and total number of boxes.
(while (re-search-forward cookie-re (cdr bounds) t)
(save-excursion
(let ((c-on 0) (c-all 0))
(save-match-data
;; There are two types of cookies: those at headings and those
;; at list items.
(cond
((and (org-on-heading-p)
(string-match "\\<todo\\>"
(downcase
(or (org-entry-get nil "COOKIE_DATA") "")))))
;; This cookie is at an heading, but specifically for
;; todo, not for checkboxes: skip it.
((org-on-heading-p)
(setq backup-end (save-excursion
(outline-next-heading) (point)))
;; This cookie is at an heading. Grab structure of
;; every list containing a checkbox between point and
;; next headline, and save them in STRUCTS-BACKUP
(while (org-list-search-forward box-re backup-end 'move)
(let* ((struct (org-list-struct))
(bottom (org-list-get-bottom-point struct)))
(push struct structs-backup)
(goto-char bottom)))
(funcall count-boxes nil structs-backup))
((org-at-item-p)
;; This cookie is at an item. Look in STRUCTS-BACKUP
;; to see if we have the structure of list at point in
;; it. Else compute the structure.
(let ((item (point-at-bol)))
(if (and backup-end (< item backup-end))
(funcall count-boxes item structs-backup)
(let ((struct (org-list-struct)))
(setq backup-end (org-list-get-bottom-point struct)
structs-backup (list struct)))
(funcall count-boxes item structs-backup))))))
;; Build the cookies list, with appropriate information
(push (list (match-beginning 1) ; cookie start
(match-end 1) ; cookie end
(match-beginning 2) ; percent?
c-on ; checked boxes
c-all) ; total boxes
cookies-list))))
(catch 'skip
(save-excursion
(let ((c-on 0) (c-all 0))
(save-match-data
;; There are two types of cookies: those at headings and those
;; at list items.
(cond
;; Cookie is at an heading, but specifically for todo,
;; not for checkboxes: skip it.
((and (org-on-heading-p)
(string-match "\\<todo\\>"
(downcase
(or (org-entry-get nil "COOKIE_DATA") ""))))
(throw 'skip nil))
;; Cookie is at an heading, but all lists before next
;; heading already have been read. Use data collected
;; in STRUCTS-BACKUP. This should only happen when
;; heading has more than one cookie on it.
((and (org-on-heading-p)
(<= (save-excursion (outline-next-heading) (point))
backup-end))
(funcall count-boxes nil structs-backup))
;; Cookie is at a fresh heading. Grab structure of
;; every list containing a checkbox between point and
;; next headline, and save them in STRUCTS-BACKUP.
((org-on-heading-p)
(setq backup-end (save-excursion
(outline-next-heading) (point)))
(while (org-list-search-forward box-re backup-end 'move)
(let* ((struct (org-list-struct))
(bottom (org-list-get-bottom-point struct)))
(push struct structs-backup)
(goto-char bottom)))
(funcall count-boxes nil structs-backup))
;; Cookie is at an item, and we already list structure
;; stored in STRUCTS-BACKUP.
((and (org-at-item-p)
(< (point-at-bol) backup-end))
(funcall count-boxes (point-at-bol) structs-backup))
;; Cookie is at an item, but we need to compute list
;; structure.
((org-at-item-p)
(let ((struct (org-list-struct)))
(setq backup-end (org-list-get-bottom-point struct)
structs-backup (list struct)))
(funcall count-boxes item structs-backup))
;; Else, cookie found is at a wrong place. Skip it.
(t (throw 'skip nil))))
;; Build the cookies list, with appropriate information
(push (list (match-beginning 1) ; cookie start
(match-end 1) ; cookie end
(match-string 2) ; percent?
c-on ; checked boxes
c-all) ; total boxes
cookies-list)))))
;; 2. Apply alist to buffer, in reverse order so positions stay
;; unchanged after cookie modifications.
(mapc (lambda (cookie)