Browse Source

Improve feedback when completing repeated tasks from agenda view.

When marking a repeated entry DONE in the daily or weekly agenda, that
task would previously still be shown as TODO, because the repeater
immediately restores the TODO state after moving the time stamp.  This
is bad feedback.

This problem was hard to fix.  Because the same line may be present in
other lines in the same weekly agenda, we cannot simply update all
lines related to this entry.

What we do now is this:  Before the repeater does its work in shifting
the time stamp and resetting the TODO keyword, we take a snapshot of
the headline as it looks then.  And then, when we update the agenda
view, we change only the line at the cursor instead of all lines
related to this entry.  We also make sure that this is only so if the
cursor is in a daily/weekly agenda, on TODAY's date.

There still remain possible inconsistencies.  For example, if you have
a daily repeating task in the weekly agenda, and you move the cursor a
few days into the future and mark it DONE there, the entry will
actually be marked DONE for today, but still show up in today's task
list as TODO.  refreshing the agenda will fix the display in such an
unlikely case.

Thanks to Jack ??? for noticing and reporting this issue.
Carsten Dominik 16 years ago
parent
commit
0bbf3a9bd6
3 changed files with 32 additions and 5 deletions
  1. 10 0
      lisp/ChangeLog
  2. 14 3
      lisp/org-agenda.el
  3. 8 2
      lisp/org.el

+ 10 - 0
lisp/ChangeLog

@@ -1,3 +1,13 @@
+2008-11-03  Carsten Dominik  <dominik@science.uva.nl>
+
+	* org-agenda.el (org-agenda-todo): Update only the current
+	headline if this is a repeated TODO, marked done for today.
+	(org-agenda-change-all-lines): New argument JUST-THIS, to change
+	only the current line.
+
+	* org.el (org-todo): Take a snapshot of the headline if the
+	repeater might change it.
+
 2008-11-02  Carsten Dominik  <dominik@science.uva.nl>
 
 	* org-publish.el (org-publish-find-title): Remove buffers visited

+ 14 - 3
lisp/org-agenda.el

@@ -4927,8 +4927,10 @@ the same tree node, and the headline of the tree node in the Org-mode file."
 	 (buffer (marker-buffer marker))
 	 (pos (marker-position marker))
 	 (hdmarker (get-text-property (point) 'org-hd-marker))
+	 (todayp (equal (get-text-property (point) 'day)
+			(time-to-days (current-time))))
 	 (inhibit-read-only t)
-	 newhead)
+	 org-agenda-headline-snapshot-before-repeat newhead just-one)
     (org-with-remote-undo buffer
       (with-current-buffer buffer
 	(widen)
@@ -4940,12 +4942,19 @@ the same tree node, and the headline of the tree node in the Org-mode file."
 	(org-todo arg)
 	(and (bolp) (forward-char 1))
 	(setq newhead (org-get-heading))
+	(when (and (org-bound-and-true-p
+		    org-agenda-headline-snapshot-before-repeat)
+		   (not (equal org-agenda-headline-snapshot-before-repeat
+			       newhead))
+		   todayp)
+	  (setq newhead org-agenda-headline-snapshot-before-repeat
+		just-one t))
 	(save-excursion
 	  (org-back-to-heading)
 	  (move-marker org-last-heading-marker (point))))
       (beginning-of-line 1)
       (save-excursion
-	(org-agenda-change-all-lines newhead hdmarker 'fixface))
+	(org-agenda-change-all-lines newhead hdmarker 'fixface just-one))
       (org-move-to-column col))))
 
 (defun org-agenda-add-note (&optional arg)
@@ -4967,7 +4976,7 @@ the same tree node, and the headline of the tree node in the Org-mode file."
 	     (org-flag-heading nil)))   ; show the next heading
       (org-add-note))))
 
-(defun org-agenda-change-all-lines (newhead hdmarker &optional fixface)
+(defun org-agenda-change-all-lines (newhead hdmarker &optional fixface just-this)
   "Change all lines in the agenda buffer which match HDMARKER.
 The new content of the line will be NEWHEAD (as modified by
 `org-format-agenda-item').  HDMARKER is checked with
@@ -4975,6 +4984,7 @@ The new content of the line will be NEWHEAD (as modified by
 If FIXFACE is non-nil, the face of each item is modified acording to
 the new TODO state."
   (let* ((inhibit-read-only t)
+	 (line (org-current-line))
 	 props m pl undone-face done-face finish new dotime cat tags)
     (save-excursion
       (goto-char (point-max))
@@ -4982,6 +4992,7 @@ the new TODO state."
       (while (not finish)
 	(setq finish (bobp))
 	(when (and (setq m (get-text-property (point) 'org-hd-marker))
+		   (or (not just-this) (= (org-current-line) line))
 		   (equal m hdmarker))
 	  (setq props (text-properties-at (point))
 		dotime (get-text-property (point) 'dotime)

+ 8 - 2
lisp/org.el

@@ -7794,7 +7794,7 @@ TODO state changes
 :from  previous state (keyword as a string), or nil
 :to    new state (keyword as a string), or nil")
 
-
+(defvar org-agenda-headline-snapshot-before-repeat)
 (defun org-todo (&optional arg)
   "Change the TODO state of an item.
 The state of an item is given by a keyword at the start of the heading,
@@ -7962,7 +7962,13 @@ For calling through lisp, arg is also interpreted in the following way:
 	    (setq head (org-get-todo-sequence-head state)))
 	(put-text-property (point-at-bol) (point-at-eol) 'org-todo-head head)
 	;; Do we need to trigger a repeat?
-	(when now-done-p (org-auto-repeat-maybe state))
+	(when now-done-p
+	  (when (boundp org-agenda-headline-snapshot-before-repeat)
+	    ;; This is for the agenda, take a snapshot of the headline.
+	    (save-match-data
+	      (setq org-agenda-headline-snapshot-before-repeat
+		    (org-get-heading))))
+	  (org-auto-repeat-maybe state))
 	;; Fixup cursor location if close to the keyword
 	(if (and (outline-on-heading-p)
 		 (not (bolp))