aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--org-drill.el43
-rw-r--r--tests/test-org-drill-session-state.el42
2 files changed, 74 insertions, 11 deletions
diff --git a/org-drill.el b/org-drill.el
index 9e38666..fd6f24e 100644
--- a/org-drill.el
+++ b/org-drill.el
@@ -119,6 +119,20 @@ Nil means unlimited."
:group 'org-drill-session
:type '(choice integer (const nil)))
+(defcustom org-drill-on-timeout-action
+ 'finish-current
+ "What to do with unfinished cards when `org-drill-maximum-duration' is reached.
+
+- `finish-current' (default): keep the historical behavior. The
+ card in progress and any cards queued for re-drilling this session
+ (the \\='again\\=' queue) are still presented before the session ends.
+- `discard-current': end the session as soon as the time limit is
+ reached, dropping the in-progress card and the again-queue. The
+ dropped cards are left untouched — they keep whatever scheduling
+ they already had and simply turn up again next session."
+ :group 'org-drill-session
+ :type '(choice (const finish-current) (const discard-current)))
+
(defcustom org-drill-item-count-includes-failed-items-p
nil
"If non-nil, count failed items in overall count.
@@ -2830,17 +2844,24 @@ Returns the value the answer presenter returned, or `skip'/`edit'/nil."
(defun org-drill-entries-pending-p (session)
"Return non-nil if SESSION still has entries left to drill.
True when an item is in progress or queued, unless the session's
-item-count or duration limit has been reached."
- (or (oref session again-entries)
- (oref session current-item)
- (and (not (org-drill-maximum-item-count-reached-p session))
- (not (org-drill-maximum-duration-reached-p session))
- (or (oref session new-entries)
- (oref session failed-entries)
- (oref session young-mature-entries)
- (oref session old-mature-entries)
- (oref session overdue-entries)
- (oref session again-entries)))))
+item-count or duration limit has been reached.
+
+When `org-drill-on-timeout-action' is `discard-current' and the
+duration limit has been reached, the in-progress card and the
+again-queue stop counting as pending, so the session ends now
+rather than finishing them."
+ (unless (and (eq org-drill-on-timeout-action 'discard-current)
+ (org-drill-maximum-duration-reached-p session))
+ (or (oref session again-entries)
+ (oref session current-item)
+ (and (not (org-drill-maximum-item-count-reached-p session))
+ (not (org-drill-maximum-duration-reached-p session))
+ (or (oref session new-entries)
+ (oref session failed-entries)
+ (oref session young-mature-entries)
+ (oref session old-mature-entries)
+ (oref session overdue-entries)
+ (oref session again-entries))))))
(defun org-drill-pending-entry-count (session)
"Return the number of entries still queued in SESSION.
diff --git a/tests/test-org-drill-session-state.el b/tests/test-org-drill-session-state.el
index 1fe58d2..3f99a8e 100644
--- a/tests/test-org-drill-session-state.el
+++ b/tests/test-org-drill-session-state.el
@@ -77,6 +77,48 @@ session look long-expired."
(eieio-oset session slot (list (make-marker-at 1)))
(should (org-drill-entries-pending-p session)))))
+;;;; org-drill-on-timeout-action — discard-current
+
+(ert-deftest test-org-drill-entries-pending-p-discard-current-times-out-drops-again ()
+ "With `discard-current' and the duration reached, the again-queue no longer
+keeps the session pending — time is up, so the re-drill items are dropped."
+ (let ((session (org-drill-session))
+ (org-drill-on-timeout-action 'discard-current)
+ (org-drill-maximum-duration 1)) ; 1-minute limit
+ (oset session start-time (- (float-time (current-time)) 3600)) ; started an hour ago
+ (oset session again-entries (list (make-marker-at 1)))
+ (should-not (org-drill-entries-pending-p session))))
+
+(ert-deftest test-org-drill-entries-pending-p-discard-current-times-out-drops-current-item ()
+ "With `discard-current' and the duration reached, a leftover current-item is
+dropped rather than forcing the session to continue."
+ (let ((session (org-drill-session))
+ (org-drill-on-timeout-action 'discard-current)
+ (org-drill-maximum-duration 1))
+ (oset session start-time (- (float-time (current-time)) 3600))
+ (oset session current-item (make-marker-at 1))
+ (should-not (org-drill-entries-pending-p session))))
+
+(ert-deftest test-org-drill-entries-pending-p-finish-current-times-out-keeps-again ()
+ "Default `finish-current' preserves the old behavior: the again-queue keeps
+the session pending even past the duration limit."
+ (let ((session (org-drill-session))
+ (org-drill-on-timeout-action 'finish-current)
+ (org-drill-maximum-duration 1))
+ (oset session start-time (- (float-time (current-time)) 3600))
+ (oset session again-entries (list (make-marker-at 1)))
+ (should (org-drill-entries-pending-p session))))
+
+(ert-deftest test-org-drill-entries-pending-p-discard-current-before-timeout-is-normal ()
+ "Before the duration is reached, `discard-current' behaves normally — queued
+items still count as pending."
+ (let ((session (org-drill-session))
+ (org-drill-on-timeout-action 'discard-current)
+ (org-drill-maximum-duration 20))
+ (oset session start-time (float-time (current-time))) ; just started
+ (oset session again-entries (list (make-marker-at 1)))
+ (should (org-drill-entries-pending-p session))))
+
;;;; org-drill-pending-entry-count
(ert-deftest test-org-drill-pending-entry-count-empty-session-zero ()