summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Ihm <marc@ihm.name>2017-04-14 17:49:50 +0200
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2017-04-17 10:33:51 +0200
commit165f7c395073b649d7da9a12c52a34b724ed4cf0 (patch)
treec506e2a1312277e62ddf130769ceea64fe177a03
parent6bd52105358ee95548d065b4ec890f451779cc90 (diff)
downloadorg-mode-165f7c395073b649d7da9a12c52a34b724ed4cf0.tar.gz
Fix explanation, if state change is blocked by contained checkboxes
* lisp/org.el (org-todo): Fix explanation, if state change is blocked by contained checkboxes. Consider a node, which contains unchecked checkboxes; if you have set org-enforce-todo-checkbox-dependencies and try to change the node to DONE, you will be denied with a message explaining why. However in this special case the explanation would be wrong in talking of an unrelated node instead of the checkboxes. The fix uses the already existing variable org-blocked-by-checkboxes (which is handled in org-block-todo-from-checkboxes). Similar code is already present in org-agenda-dim-blocked-tasks within org-agenda.el.
-rw-r--r--lisp/org.el58
1 files changed, 31 insertions, 27 deletions
diff --git a/lisp/org.el b/lisp/org.el
index 17dd46b..1a17032 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -12585,7 +12585,8 @@ nil or a string to be used for the todo mark." )
bound1 t))
(replace-match "0" t nil nil 1)))))
-(defvar org-state) ;; dynamically scoped into this function
+(defvar org-state)
+(defvar org-blocked-by-checkboxes)
(defun org-todo (&optional arg)
"Change the TODO state of an item.
@@ -12675,12 +12676,12 @@ When called through ELisp, arg is also interpreted in the following way:
(and (not arg) org-use-fast-todo-selection
(not (eq org-use-fast-todo-selection
'prefix)))))
- ;; Use fast selection
+ ;; Use fast selection.
(org-fast-todo-selection))
((and (equal arg '(4))
(or (not org-use-fast-todo-selection)
(not org-todo-key-trigger)))
- ;; Read a state with completion
+ ;; Read a state with completion.
(completing-read
"State: " (mapcar #'list org-todo-keywords-1)
nil t))
@@ -12696,9 +12697,9 @@ When called through ELisp, arg is also interpreted in the following way:
org-todo-keywords-1)
(org-last org-todo-keywords-1))))
((and (eq org-use-fast-todo-selection t) (equal arg '(4))
- (setq arg nil))) ; hack to fall back to cycling
+ (setq arg nil))) ;hack to fall back to cycling
(arg
- ;; user or caller requests a specific state
+ ;; User or caller requests a specific state.
(cond
((equal arg "") nil)
((eq arg 'none) nil)
@@ -12716,8 +12717,8 @@ When called through ELisp, arg is also interpreted in the following way:
((nth (1- (prefix-numeric-value arg))
org-todo-keywords-1))))
((null member) (or head (car org-todo-keywords-1)))
- ((equal this final-done-word) nil) ;; -> make empty
- ((null tail) nil) ;; -> first entry
+ ((equal this final-done-word) nil) ;-> make empty
+ ((null tail) nil) ;-> first entry
((memq interpret '(type priority))
(if (eq this-command last-command)
(car tail)
@@ -12735,20 +12736,24 @@ When called through ELisp, arg is also interpreted in the following way:
:position startpos))
dolog now-done-p)
(when org-blocker-hook
- (setq org-last-todo-state-is-todo
- (not (member this org-done-keywords)))
- (unless (save-excursion
- (save-match-data
- (org-with-wide-buffer
- (run-hook-with-args-until-failure
- 'org-blocker-hook change-plist))))
- (if (called-interactively-p 'interactive)
- (user-error "TODO state change from %s to %s blocked (by \"%s\")"
- this org-state org-block-entry-blocking)
- ;; fail silently
- (message "TODO state change from %s to %s blocked (by \"%s\")"
- this org-state org-block-entry-blocking)
- (throw 'exit nil))))
+ (let (org-blocked-by-checkboxes block-reason)
+ (setq org-last-todo-state-is-todo
+ (not (member this org-done-keywords)))
+ (unless (save-excursion
+ (save-match-data
+ (org-with-wide-buffer
+ (run-hook-with-args-until-failure
+ 'org-blocker-hook change-plist))))
+ (setq block-reason (if org-blocked-by-checkboxes
+ "contained checkboxes"
+ (format "\"%s\"" org-block-entry-blocking)))
+ (if (called-interactively-p 'interactive)
+ (user-error "TODO state change from %s to %s blocked (by %s)"
+ this org-state block-reason)
+ ;; Fail silently.
+ (message "TODO state change from %s to %s blocked (by %s)"
+ this org-state block-reason)
+ (throw 'exit nil)))))
(store-match-data match-data)
(replace-match next t t)
(cond ((equal this org-state)
@@ -12775,7 +12780,7 @@ When called through ELisp, arg is also interpreted in the following way:
(when (and (or org-todo-log-states org-log-done)
(not (eq org-inhibit-logging t))
(not (memq arg '(nextset previousset))))
- ;; we need to look at recording a time and note
+ ;; We need to look at recording a time and note.
(setq dolog (or (nth 1 (assoc org-state org-todo-log-states))
(nth 2 (assoc this org-todo-log-states))))
(when (and (eq dolog 'note) (eq org-inhibit-logging 'note))
@@ -12788,14 +12793,14 @@ When called through ELisp, arg is also interpreted in the following way:
;; If there was a CLOSED time stamp, get rid of it.
(org-add-planning-info nil nil 'closed))
(when (and now-done-p org-log-done)
- ;; It is now done, and it was not done before
+ ;; It is now done, and it was not done before.
(org-add-planning-info 'closed (org-current-effective-time))
(when (and (not dolog) (eq 'note org-log-done))
(org-add-log-setup 'done org-state this 'note)))
(when (and org-state dolog)
- ;; This is a non-nil state, and we need to log it
+ ;; This is a non-nil state, and we need to log it.
(org-add-log-setup 'state org-state this dolog)))
- ;; Fixup tag positioning
+ ;; Fixup tag positioning.
(org-todo-trigger-tag-changes org-state)
(and org-auto-align-tags (not org-setting-tags) (org-set-tags nil t))
(when org-provide-todo-statistics
@@ -12812,7 +12817,7 @@ When called through ELisp, arg is also interpreted in the following way:
(setq org-agenda-headline-snapshot-before-repeat
(org-get-heading))))
(org-auto-repeat-maybe org-state))
- ;; Fixup cursor location if close to the keyword
+ ;; Fixup cursor location if close to the keyword.
(when (and (outline-on-heading-p)
(not (bolp))
(save-excursion (beginning-of-line 1)
@@ -12931,7 +12936,6 @@ See variable `org-track-ordered-property-with-tag'."
(and tag (org-toggle-tag tag 'on))
(message "Subtasks must be completed in sequence")))))
-(defvar org-blocked-by-checkboxes) ; dynamically scoped
(defun org-block-todo-from-checkboxes (change-plist)
"Block turning an entry into a TODO, using checkboxes.
This checks whether the current task should be blocked from state