org-agenda: Fix meaning of 'repeated-after-deadline value of `org-agenda-skip-scheduled-if-deadline-is-shown'

* lisp/org-agenda.el (org-agenda-skip-scheduled-if-deadline-is-shown):
Move 'repeated-after-deadline value into a new custom option.
(org-agenda-skip-scheduled-repeats-after-deadline): Create a new
custom option to make agenda hide scheduled entries repeated past
deadline.
* lisp/org-agenda.el (org-agenda-get-scheduled): Use the new custom
option.  Do not demand deadline to be actually shown when deciding
whether to skip scheduled repeats past deadline.  This fixes a bug
when repeats continue to be displayed if past deadline is not
displayed within agenda span.
* doc/org-manual.org (Repeated tasks): Adjust manual entry, mentioning
the new custom option.
* etc/ORG-NEWS (~repeated-after-deadline~ value of
~org-agenda-skip-scheduled-repeats-after-deadline~ is moved to a new
customization): Announce the change.
*
testing/lisp/test-org-agenda.el (test-org-agenda/skip-scheduled-repeats-after-deadline):
Add new test.

Reported-by: Morgan Smith <Morgan.J.Smith@outlook.com>
Link: https://orgmode.org/list/874jft6vpj.fsf@localhost
This commit is contained in:
Ihor Radchenko 2024-02-07 13:21:34 +01:00
parent 18d98ee655
commit b26745b985
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
4 changed files with 104 additions and 21 deletions

View File

@ -6680,16 +6680,16 @@ special repeaters =++= and =.+=. For example:
Marking this DONE shifts the date to exactly one hour from now. Marking this DONE shifts the date to exactly one hour from now.
#+end_example #+end_example
#+vindex: org-agenda-skip-scheduled-if-deadline-is-shown #+vindex: org-agenda-skip-scheduled-repeats-after-deadline
You may have both scheduling and deadline information for a specific You may have both scheduling and deadline information for a specific
task. If the repeater is set for the scheduling information only, you task. If the repeater is set for the scheduling information only, you
probably want the repeater to be ignored after the deadline. If so, probably want the repeater to be ignored after the deadline. If so,
set the variable ~org-agenda-skip-scheduled-if-deadline-is-shown~ to set the variable ~org-agenda-skip-scheduled-repeats-after-deadline~ to
~repeated-after-deadline~. However, any scheduling information ~t~. However, any scheduling information without a repeater is no
without a repeater is no longer relevant once the task is done, and longer relevant once the task is done, and thus, removed upon
thus, removed upon repeating the task. If you want both scheduling repeating the task. If you want both scheduling and deadline
and deadline information to repeat after the same interval, set the information to repeat after the same interval, set the same repeater
same repeater for both timestamps. for both timestamps.
An alternative to using a repeater is to create a number of copies of An alternative to using a repeater is to create a number of copies of
a task subtree, with dates shifted in each copy. The command a task subtree, with dates shifted in each copy. The command

View File

@ -469,6 +469,23 @@ The change is breaking when ~org-use-property-inheritance~ is set to ~t~.
The =TEST= parameter is better served by Emacs debugging tools. The =TEST= parameter is better served by Emacs debugging tools.
** New and changed options ** New and changed options
*** ~repeated-after-deadline~ value of ~org-agenda-skip-scheduled-repeats-after-deadline~ is moved to a new customization
A new custom option ~org-agenda-skip-scheduled-repeats-after-deadline~
is introduced in place of ~repeated-after-deadline~ value of
~org-agenda-skip-scheduled-repeats-after-deadline~.
Introducing a new option allow more control over agenda display and
resolves a confusion about the meaning of ~repeated-after-deadline~.
~repeated-after-deadline~ has nothing to do with /showing/ deadline.
It just prevents agenda display repeated scheduled entries past
deadline. The following example illustrates the meaning:
: * TODO Do me every day before Jan, 12th (included)
: SCHEDULED: <2024-01-03 Wed +1d> DEADLINE: <2024-01-05 Fri>
The old customization will continue to work, ensuring backwards compatibility.
*** New custom setting ~org-icalendar-ttl~ for the ~ox-icalendar~ backend *** New custom setting ~org-icalendar-ttl~ for the ~ox-icalendar~ backend
The option ~org-icalendar-ttl~ allows to advise a subscriber to the The option ~org-icalendar-ttl~ allows to advise a subscriber to the

View File

@ -894,17 +894,13 @@ the entry is scheduled today or was scheduled previously is not
shown. shown.
When set to the symbol `not-today', skip scheduled previously, When set to the symbol `not-today', skip scheduled previously,
but not scheduled today. but not scheduled today."
When set to the symbol `repeated-after-deadline', skip scheduled
items if they are repeated beyond the current deadline."
:group 'org-agenda-skip :group 'org-agenda-skip
:group 'org-agenda-daily/weekly :group 'org-agenda-daily/weekly
:type '(choice :type '(choice
(const :tag "Never" nil) (const :tag "Never" nil)
(const :tag "Always" t) (const :tag "Always" t)
(const :tag "Not when scheduled today" not-today) (const :tag "Not when scheduled today" not-today)))
(const :tag "When repeated past deadline" repeated-after-deadline)))
(defcustom org-agenda-skip-timestamp-if-deadline-is-shown nil (defcustom org-agenda-skip-timestamp-if-deadline-is-shown nil
"Non-nil means skip timestamp line if same entry shows because of deadline. "Non-nil means skip timestamp line if same entry shows because of deadline.
@ -1341,10 +1337,16 @@ When set to the symbol `next' only the first future repeat is shown."
(const :tag "Show all repeated entries" t) (const :tag "Show all repeated entries" t)
(const :tag "Show next repeated entry" next) (const :tag "Show next repeated entry" next)
(const :tag "Do not show repeated entries" nil)) (const :tag "Do not show repeated entries" nil))
:version "26.1"
:package-version '(Org . "9.1") :package-version '(Org . "9.1")
:safe #'symbolp) :safe #'symbolp)
(defcustom org-agenda-skip-scheduled-repeats-after-deadline nil
"Non-nil hides scheduled repeated entries past deadline."
:group 'org-agenda-daily/weekly
:type 'boolean
:package-version '(Org . "9.7")
:safe t)
(defcustom org-agenda-prefer-last-repeat nil (defcustom org-agenda-prefer-last-repeat nil
"Non-nil sets date for repeated entries to their last repeat. "Non-nil sets date for repeated entries to their last repeat.
@ -6661,18 +6663,25 @@ scheduled items with an hour specification like [h]h:mm."
;; Skip entry if it already appears as a deadline, per ;; Skip entry if it already appears as a deadline, per
;; `org-agenda-skip-scheduled-if-deadline-is-shown'. This ;; `org-agenda-skip-scheduled-if-deadline-is-shown'. This
;; doesn't apply to habits. ;; doesn't apply to habits.
(when (or org-agenda-skip-scheduled-repeats-after-deadline
;; FIXME: Backwards-compatibility.
(eq org-agenda-skip-scheduled-if-deadline-is-shown
'repeated-after-deadline))
(let ((deadline
(time-to-days
(when (org-element-property :deadline el)
(org-time-string-to-time
(org-element-interpret-data
(org-element-property :deadline el)))))))
(when (and (or (<= (org-agenda--timestamp-to-absolute s) deadline)
(not (= schedule current)))
(> current deadline))
(throw :skip nil))))
(when (pcase org-agenda-skip-scheduled-if-deadline-is-shown (when (pcase org-agenda-skip-scheduled-if-deadline-is-shown
((guard ((guard
(or (not (memq (line-beginning-position 0) deadline-pos)) (or (not (memq (line-beginning-position 0) deadline-pos))
habitp)) habitp))
nil) nil)
(`repeated-after-deadline
(let ((deadline (time-to-days
(when (org-element-property :deadline el)
(org-time-string-to-time
(org-element-interpret-data
(org-element-property :deadline el)))))))
(and (<= schedule deadline) (> current deadline))))
(`not-today pastschedp) (`not-today pastschedp)
(`t t) (`t t)
(_ nil)) (_ nil))

View File

@ -590,6 +590,63 @@ DEADLINE: " (cdr timestamp))))
(org-agenda nil "f") (org-agenda nil "f")
(buffer-string)))))))))))) (buffer-string))))))))))))
(ert-deftest test-org-agenda/skip-scheduled-repeats-after-deadline ()
"Test `org-agenda-skip-scheduled-repeats-after-deadline'."
(cl-assert (not org-agenda-sticky) nil "precondition violation")
(cl-assert (not (org-test-agenda--agenda-buffers))
nil "precondition violation")
(dolist (org-agenda-skip-scheduled-repeats-after-deadline '(nil t))
(org-test-at-time "2024-01-01 8:00"
(org-test-with-temp-text-in-file "
* TODO Do me every day before Jan, 12th (included)
SCHEDULED: <2024-01-03 Wed +1d> DEADLINE: <2024-01-05 Fri>
"
(let ((org-agenda-span 'week)
(org-agenda-files `(,(buffer-file-name))))
;; NOTE: Be aware that `org-agenda-list' may or may not display
;; past scheduled items depending whether the date is today
;; `org-today' or not.
(org-agenda-list nil "<2024-01-01 Mon>")
(set-buffer org-agenda-buffer-name)
(if org-agenda-skip-scheduled-repeats-after-deadline
(should
;; Not displayed after deadline.
(string-match-p
"Week-agenda (W01):
Monday 1 January 2024 W01
[^:]+:In 4 d.: TODO Do me every day before Jan, 12th (included)
Tuesday 2 January 2024
Wednesday 3 January 2024
[^:]+:Scheduled: TODO Do me every day before Jan, 12th (included)
Thursday 4 January 2024
[^:]+:Scheduled: TODO Do me every day before Jan, 12th (included)
Friday 5 January 2024
[^:]+:Scheduled: TODO Do me every day before Jan, 12th (included)
[^:]+:Deadline: TODO Do me every day before Jan, 12th (included)
Saturday 6 January 2024
Sunday 7 January 2024"
(buffer-string)))
(should
;; Displayed after deadline.
(string-match-p
"Week-agenda (W01):
Monday 1 January 2024 W01
[^:]+:In 4 d.: TODO Do me every day before Jan, 12th (included)
Tuesday 2 January 2024
Wednesday 3 January 2024
[^:]+:Scheduled: TODO Do me every day before Jan, 12th (included)
Thursday 4 January 2024
[^:]+:Scheduled: TODO Do me every day before Jan, 12th (included)
Friday 5 January 2024
[^:]+:Scheduled: TODO Do me every day before Jan, 12th (included)
[^:]+:Deadline: TODO Do me every day before Jan, 12th (included)
Saturday 6 January 2024
[^:]+:Scheduled: TODO Do me every day before Jan, 12th (included)
Sunday 7 January 2024
[^:]+:Scheduled: TODO Do me every day before Jan, 12th (included)"
(buffer-string))))))
(org-test-agenda--kill-all-agendas))))
(ert-deftest test-org-agenda/goto-date () (ert-deftest test-org-agenda/goto-date ()
"Test `org-agenda-goto-date'." "Test `org-agenda-goto-date'."
(unwind-protect (unwind-protect