Browse Source

Prevent infinite loop when showing new time in agenda

* lisp/org-agenda.el (org-agenda-dim-blocked-tasks): Don't use
an overlay to make the task invisible, use text properties.
(org-agenda--mark-blocked-entry): Add text property
'org-filter-type to later use `org-agenda-filter-hide-line' if
necessary.
(org-agenda-filter-hide-line): Fix docstring.

The related bug was first reported in 2013 by Matt Lundin here:
https://lists.gnu.org/archive/html/emacs-orgmode/2013-08/msg00072.html

Then Andrew Hyatt reported it again, and provided a minimal recipe on
how to reproduce it consistently.

Thanks a lot to both of them.
Bastien 5 months ago
parent
commit
27e4d7ce48
1 changed files with 19 additions and 13 deletions
  1. 19 13
      lisp/org-agenda.el

+ 19 - 13
lisp/org-agenda.el

@@ -4003,7 +4003,7 @@ dimming them."
   (when (called-interactively-p 'interactive)
     (message "Dim or hide blocked tasks..."))
   (dolist (o (overlays-in (point-min) (point-max)))
-    (when (eq (overlay-get o 'org-type) 'org-blocked-todo)
+    (when (eq (overlay-get o 'face) 'org-agenda-dimmed-todo-face)
       (delete-overlay o)))
   (save-excursion
     (let ((inhibit-read-only t))
@@ -4011,22 +4011,26 @@ dimming them."
       (while (let ((pos (text-property-not-all
 			 (point) (point-max) 'org-todo-blocked nil)))
 	       (when pos (goto-char pos)))
-	(let* ((invisible (eq (org-get-at-bol 'org-todo-blocked) 'invisible))
+	(let* ((invisible
+		(eq (org-get-at-bol 'org-todo-blocked) 'invisible))
+	       (todo-blocked
+		(eq (org-get-at-bol 'org-filter-type) 'todo-blocked))
 	       (ov (make-overlay (if invisible
 				     (line-end-position 0)
 				   (line-beginning-position))
 				 (line-end-position))))
-	  (if invisible
-	      (overlay-put ov 'invisible t)
+	  (when todo-blocked
 	    (overlay-put ov 'face 'org-agenda-dimmed-todo-face))
-	  (overlay-put ov 'org-type 'org-blocked-todo))
-	(forward-line))))
+	  (when invisible
+	    (org-agenda-filter-hide-line 'todo-blocked)))
+	(move-beginning-of-line 2))))
   (when (called-interactively-p 'interactive)
     (message "Dim or hide blocked tasks...done")))
 
 (defun org-agenda--mark-blocked-entry (entry)
-  "For ENTRY a string with the text property `org-hd-marker', if
-the header at `org-hd-marker' is blocked according to
+  "If ENTRY is blocked, mark it for fontification or invisibility.
+
+If the header at `org-hd-marker' is blocked according to
 `org-entry-blocked-p', then if `org-agenda-dim-blocked-tasks' is
 'invisible and the header is not blocked by checkboxes, set the
 text property `org-todo-blocked' to `invisible', otherwise set it
@@ -4050,7 +4054,9 @@ to t."
 	      (put-text-property
 	       0 (length entry) 'org-todo-blocked
 	       (if really-invisible 'invisible t)
-	       entry)))))))
+	       entry)
+	      (put-text-property
+	       0 (length entry) 'org-filter-type 'todo-blocked entry)))))))
   entry)
 
 (defvar org-agenda-skip-function nil
@@ -8064,13 +8070,13 @@ tags in the FILTER if any of the tags in FILTER are grouptags."
 	org-agenda-filtered-by-top-headline t))
 
 (defun org-agenda-filter-hide-line (type)
-  "Hide lines with TYPE in the agenda buffer."
+  "If current line is TYPE, hide it in the agenda buffer."
   (let* (buffer-invisibility-spec
-	 (b (max (point-min) (1- (point-at-bol))))
-	 (e (point-at-eol)))
+	 (beg (max (point-min) (1- (point-at-bol))))
+	 (end (point-at-eol)))
     (let ((inhibit-read-only t))
       (add-text-properties
-       b e `(invisible org-filtered org-filter-type ,type)))))
+       beg end `(invisible org-filtered org-filter-type ,type)))))
 
 (defun org-agenda-remove-filter (type)
   (interactive)