summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2010-07-28 15:53:37 +0200
committerNicolas Goaziou <n.goaziou@gmail.com>2010-09-01 19:05:51 +0200
commit4d40259e56928853330c3adeb2bb19f0dcc91320 (patch)
tree198dfbe61e89784a3e8b00122d7a1628aca00480
parentc444086ade2f909a9721533de1a4eff009014f17 (diff)
downloadorg-mode-4d40259e56928853330c3adeb2bb19f0dcc91320.tar.gz
Better handling of checkboxes with regards to [@start:x] constructs
* org.el (org-set-font-lock-defaults): Correct fontification for checkboxes found after [@start:?]. * org-list.el (org-list-at-regexp-after-bullet-p): skip any [@start:?] when looking at a regex after a bullet. * org-list.el (org-toggle-checkbox): correct insertion of checkboxes when there is already a [@start:?] in the item. * org-list.el (org-checkbox-blocked-p): properly check if there's an unchecked item before. * org-list.el (org-list-parse-list): function handles items having both a counter and a checkbox.
-rw-r--r--lisp/org-list.el150
-rw-r--r--lisp/org.el2
2 files changed, 78 insertions, 74 deletions
diff --git a/lisp/org-list.el b/lisp/org-list.el
index 843ddba..c0799d3 100644
--- a/lisp/org-list.el
+++ b/lisp/org-list.el
@@ -322,6 +322,9 @@ the end of the nearest terminator from max."
(and (org-at-item-p)
(save-excursion
(goto-char (match-end 0))
+ ;; Ignore counter if any
+ (when (looking-at "\\(?:\\[@start:[0-9]+\\][ \t]*\\)?")
+ (goto-char (match-end 0)))
(looking-at regexp))))
(defun org-list-get-item-same-level (search-fun pos limit pre-move)
@@ -465,8 +468,7 @@ function ends."
(defun org-at-item-p ()
"Is point in a line starting a hand-formatted item?"
(save-excursion
- (goto-char (point-at-bol))
- (looking-at org-item-beginning-re)))
+ (beginning-of-line) (looking-at org-item-beginning-re)))
(defun org-at-item-bullet-p ()
"Is point at the bullet of a plain list item?"
@@ -513,7 +515,8 @@ A checkbox is blocked if all of the following conditions are fulfilled:
(condition-case nil (org-back-to-heading t)
(error (throw 'exit nil)))
(unless (org-entry-get nil "ORDERED") (throw 'exit nil))
- (when (org-search-forward-unenclosed "^[ \t]*[-+*0-9.)] \\[[- ]\\]" end t)
+ (when (org-search-forward-unenclosed
+ "^[ \t]*[-+*0-9.)]+[ \t]+\\(\\[@start:[0-9]+\\][ \t]+\\)?\\[[- ]\\]" end t)
(org-current-line)))))))
;;; Navigate
@@ -1105,73 +1108,74 @@ is an integer, 0 means `-', 1 means `+' etc. If WHICH is
(defun org-toggle-checkbox (&optional toggle-presence)
"Toggle the checkbox in the current line.
-With prefix arg TOGGLE-PRESENCE, add or remove checkboxes.
-With double prefix, set checkbox to [-].
-When there is an active region, toggle status or presence of the checkbox
-in the first line, and make every item in the region have the same
-status or presence, respectively.
-If the cursor is in a headline, apply this to all checkbox items in the
-text below the heading."
+
+With prefix arg TOGGLE-PRESENCE, add or remove checkboxes. With
+double prefix, set checkbox to [-].
+
+When there is an active region, toggle status or presence of the
+checkbox in the first line, and make every item in the region
+have the same status or presence, respectively.
+
+If the cursor is in a headline, apply this to all checkbox items
+in the text below the heading, taking as reference the first item
+in subtree."
(interactive "P")
- (catch 'exit
- (let (beg end status first-present first-status blocked)
- (cond
- ((org-region-active-p)
- (setq beg (region-beginning) end (region-end)))
- ((org-on-heading-p)
- (setq beg (point) end (save-excursion (outline-next-heading) (point))))
- ((org-at-item-checkbox-p)
- (save-excursion
- (if (equal toggle-presence '(4))
- (progn
- (replace-match "" nil nil nil 1)
- (goto-char (match-beginning 0))
- (just-one-space))
- (when (setq blocked (org-checkbox-blocked-p))
- (error "Checkbox blocked because of unchecked box in line %d"
- blocked))
- (replace-match
- (cond ((equal toggle-presence '(16)) "[-]")
- ((member (match-string 1) '("[ ]" "[-]")) "[X]")
- (t "[ ]"))
- t t nil 1)))
- (throw 'exit t))
- ((org-at-item-p)
- ;; add a checkbox if point is not at a description item
- (save-excursion
- (goto-char (match-end 0))
- (if (org-at-item-description-p)
- (error "Cannot add a checkbox in a description list")
- (insert "[ ] ")))
- (throw 'exit t))
- (t (error "Not at a checkbox or heading, and no active region")))
- (setq end (move-marker (make-marker) end))
- (save-excursion
- (goto-char beg)
- (setq first-present (org-at-item-checkbox-p)
- first-status
- (save-excursion
- (and (org-search-forward-unenclosed "[ \t]\\(\\[[ X]\\]\\)" end t)
- (equal (match-string 0) "[X]"))))
- (while (< (point) end)
- (if toggle-presence
- (cond
- ((and first-present (org-at-item-checkbox-p))
- (save-excursion
- (replace-match "")
- (goto-char (match-beginning 0))
- (just-one-space)))
- ((and (not first-present) (not (org-at-item-checkbox-p))
- (org-at-item-p))
- (save-excursion
- (goto-char (match-end 0))
- (insert "[ ] "))))
- (when (org-at-item-checkbox-p)
- (setq status (equal (match-string 1) "[X]"))
- (replace-match
- (if first-status "[ ]" "[X]") t t nil 1)))
- (beginning-of-line 2)))))
- (org-update-checkbox-count-maybe))
+ ;; Bounds is a list of type (beg end single-p) where single-p is t
+ ;; when `org-toggle-checkbox' is applied to a single item. Only
+ ;; toggles on single items will return errors.
+ (let* ((bounds
+ (cond
+ ((org-region-active-p)
+ (list (region-beginning) (region-end) nil))
+ ((org-on-heading-p)
+ ;; In this case, reference line is the first item in subtree
+ (let ((limit (save-excursion (outline-next-heading) (point))))
+ (save-excursion
+ (org-search-forward-unenclosed org-item-beginning-re limit 'move)
+ (list (point) limit nil))))
+ ((org-at-item-p)
+ (list (point-at-bol) (point-at-eol) t))
+ (t (error "Not at an item or heading, and no active region"))))
+ ;; marker is needed because deleting checkboxes will change END
+ (end (copy-marker (nth 1 bounds)))
+ (single-p (nth 2 bounds))
+ (ref-presence (save-excursion (goto-char (car bounds)) (org-at-item-checkbox-p)))
+ (ref-status (equal (match-string 1) "[X]"))
+ (act-on-item
+ (lambda (ref-pres ref-stat)
+ (if (equal toggle-presence '(4))
+ (cond
+ ((and ref-pres (org-at-item-checkbox-p))
+ (replace-match ""))
+ ((and (not ref-pres)
+ (not (org-at-item-checkbox-p))
+ (org-at-item-p))
+ (goto-char (match-end 0))
+ ;; Ignore counter, if any
+ (when (looking-at "\\(?:\\[@start:[0-9]+\\][ \t]*\\)?")
+ (goto-char (match-end 0)))
+ (let ((desc-p (and (org-at-item-description-p)
+ (cdr (assq 'checkbox org-list-automatic-rules)))))
+ (cond
+ ((and single-p desc-p)
+ (error "Cannot add a checkbox in a description list"))
+ ((not desc-p) (insert "[ ] "))))))
+ (let ((blocked (org-checkbox-blocked-p)))
+ (cond
+ ((and blocked single-p)
+ (error "Checkbox blocked because of unchecked box in line %d" blocked))
+ (blocked nil)
+ ((org-at-item-checkbox-p)
+ (replace-match
+ (cond ((equal toggle-presence '(16)) "[-]")
+ (ref-stat "[ ]")
+ (t "[X]"))
+ t t nil 1))))))))
+ (save-excursion
+ (while (< (point) end)
+ (funcall act-on-item ref-presence ref-status)
+ (org-search-forward-unenclosed org-item-beginning-re end 'move)))
+ (org-update-checkbox-count-maybe)))
(defun org-reset-checkbox-state-subtree ()
"Reset all checkboxes in an entry subtree."
@@ -1455,11 +1459,11 @@ sublevels as a list of strings."
(nextitem (or (org-get-next-item (point) end) end))
(item (org-trim (buffer-substring (point) (org-end-of-item-or-at-child))))
(nextindent (if (= (point) end) 0 (org-get-indentation)))
- (item (if (string-match "^\\[\\([xX ]\\)\\]" item)
+ (item (if (string-match "^\\(?:\\[@start:[0-9]+\\][ \t]+\\)?\\[\\([xX ]\\)\\]" item)
(replace-match (if (equal (match-string 1 item) " ")
- "[CBOFF]"
- "[CBON]")
- t nil item)
+ "CBOFF"
+ "CBON")
+ t nil item 1)
item)))
(push item output)
(when (> nextindent indent1)
diff --git a/lisp/org.el b/lisp/org.el
index e4e39e9..2f100b7 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5457,7 +5457,7 @@ needs to be inserted at a specific position in the font-lock sequence.")
'(org-do-emphasis-faces (0 nil append))
'(org-do-emphasis-faces)))
;; Checkboxes
- '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[- X]\\]\\)"
+ '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\(?:[ \t]+\\[@start:[0-9]+\\]\\)?\\)[ \t]+\\(\\[[- X]\\]\\)"
2 'org-checkbox prepend)
(if org-provide-checkbox-statistics
'("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"