emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/org-drill 9cb409a1ba 012/251: * New command: 'M-x org-dril


From: ELPA Syncer
Subject: [nongnu] elpa/org-drill 9cb409a1ba 012/251: * New command: 'M-x org-drill-cram'. "Cram Mode" is the same as an ordinary drill session, except
Date: Mon, 17 Jan 2022 18:58:56 -0500 (EST)

branch: elpa/org-drill
commit 9cb409a1ba2556072f82bcaba5331b72e6876aad
Author: eeeickythump <devnull@localhost>
Commit: eeeickythump <devnull@localhost>

    * New command: 'M-x org-drill-cram'. "Cram Mode" is the same as an ordinary 
drill session, except
      that ALL items are considered "due for review" unless they have been 
reviewed within the last
      few hours (the number of hours is configurable by setting 
'org-drill-cram-hours'). This
      mode is intended for quickly revising a collection of drill items before 
a test.
    * New card type: multicloze. Behaves the same as "simple" cards, but when 
there is more than one
      portion marked as cloze text, only ONE of the marked portions will be 
hidden during review
      (chosen at random) -- the rest will all be visible. This means that a 
sentence containing
      several facts can be easily turned into a drill item by marking each fact.
    * During review, the count of "done" items is displayed.
    * After rating your recall of an item, the number of days until its next 
review is briefly shown
      in the minibuffer.
    * In org buffers, the "hint" portion of cloze text now has its own face.
---
 org-drill.el | 336 +++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 233 insertions(+), 103 deletions(-)

diff --git a/org-drill.el b/org-drill.el
index 8485d0faaa..a0b0f1bd7d 100644
--- a/org-drill.el
+++ b/org-drill.el
@@ -1,7 +1,7 @@
 ;;; org-drill.el - Self-testing with org-learn
 ;;;
 ;;; Author: Paul Sexton <eeeickythump@gmail.com>
-;;; Version: 1.3.1
+;;; Version: 1.4
 ;;; Repository at http://bitbucket.org/eeeickythump/org-drill/
 ;;;
 ;;;
@@ -96,6 +96,12 @@ Possible values:
 
 
 (defface org-drill-visible-cloze-face
+  '((t (:foreground "darkseagreen")))
+  "The face used to hide the contents of cloze phrases."
+  :group 'org-drill)
+
+
+(defface org-drill-visible-cloze-hint-face
   '((t (:foreground "dark slate blue")))
   "The face used to hide the contents of cloze phrases."
   :group 'org-drill)
@@ -136,6 +142,13 @@ during a drill session."
   :group 'org-drill
   :type 'color)
 
+(defcustom org-drill-done-count-color
+  "sienna"
+  "Foreground colour used to display the count of reviewed items
+during a drill session."
+  :group 'org-drill
+  :type 'color)
+
 
 (setplist 'org-drill-cloze-overlay-defaults
           '(display "[...]"
@@ -146,7 +159,15 @@ during a drill session."
 (defvar org-drill-cloze-regexp
   ;; ver 1   "[^][]\\(\\[[^][][^]]*\\]\\)"
   ;; ver 2   "\\(\\[.*?\\]\\|^[^[[:cntrl:]]*?\\]\\|\\[.*?$\\)"
-  "\\(\\[.*?\\]\\|\\[.*?[[:cntrl:]]+.*?\\]\\)")
+  ;; ver 3!  "\\(\\[.*?\\]\\|\\[.*?[[:cntrl:]]+.*?\\]\\)"
+  "\\(\\[[[:cntrl:][:graph:][:space:]]*?\\)\\(\\||.+?\\)\\(\\]\\)")
+
+(defvar org-drill-cloze-keywords
+  `((,org-drill-cloze-regexp
+     (1 'org-drill-visible-cloze-face nil)
+     (2 'org-drill-visible-cloze-hint-face t)
+     (3 'org-drill-visible-cloze-face nil)
+     )))
 
 
 (defcustom org-drill-card-type-alist
@@ -154,6 +175,7 @@ during a drill session."
     ("simple" . org-drill-present-simple-card)
     ("twosided" . org-drill-present-two-sided-card)
     ("multisided" . org-drill-present-multi-sided-card)
+    ("multicloze" . org-drill-present-multicloze)
     ("spanish_verb" . org-drill-present-spanish-verb))
   "Alist associating card types with presentation functions. Each entry in the
 alist takes the form (CARDTYPE . FUNCTION), where CARDTYPE is a string
@@ -180,6 +202,13 @@ random noise is adapted from Mnemosyne."
   :group 'org-drill
   :type 'boolean)
 
+(defcustom org-drill-cram-hours
+  12
+  "When in cram mode, items are considered due for review if
+they were reviewed at least this many hours ago."
+  :group 'org-drill
+  :type 'integer)
+
 
 (defvar *org-drill-session-qualities* nil)
 (defvar *org-drill-start-time* 0)
@@ -188,6 +217,10 @@ random noise is adapted from Mnemosyne."
 (defvar *org-drill-failed-entries* nil)
 (defvar *org-drill-again-entries* nil)
 (defvar *org-drill-done-entries* nil)
+(defvar *org-drill-cram-mode* nil
+  "Are we in 'cram mode', where all items are considered due
+for review unless they were already reviewed in the recent past?")
+
 
 
 ;;;; Utilities ================================================================
@@ -222,6 +255,47 @@ random noise is adapted from Mnemosyne."
   list)
     
 
+(defun time-to-inactive-org-timestamp (time)
+  (format-time-string 
+   (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")
+   time))
+
+
+
+(defmacro with-hidden-cloze-text (&rest body)
+  `(progn
+     (org-drill-hide-clozed-text)
+     (unwind-protect
+         (progn
+           ,@body)
+       (org-drill-unhide-clozed-text))))
+
+
+(defun org-drill-days-since-last-review ()
+  "Nil means a last review date has not yet been stored for
+the item.
+Zero means it was reviewed today.
+A positive number means it was reviewed that many days ago.
+A negative number means the date of last review is in the future --
+this should never happen."
+  (let ((datestr (org-entry-get (point) "DRILL_LAST_REVIEWED")))
+    (when datestr
+      (- (time-to-days (current-time))
+         (time-to-days (apply 'encode-time
+                              (org-parse-time-string datestr)))))))
+
+
+(defun org-drill-hours-since-last-review ()
+  "Like `org-drill-days-since-last-review', but return value is
+in hours rather than days."
+  (let ((datestr (org-entry-get (point) "DRILL_LAST_REVIEWED")))
+    (when datestr
+      (floor
+       (/ (- (time-to-seconds (current-time))
+             (time-to-seconds (apply 'encode-time
+                                     (org-parse-time-string datestr))))
+          (* 60 60))))))
+
 
 (defun org-drill-entry-p ()
   "Is the current entry a 'drill item'?"
@@ -258,14 +332,21 @@ drill entry."
 
 
 (defun org-drill-entry-due-p ()
-  (let ((item-time (org-get-scheduled-time (point))))
-    (and (org-drill-entry-p)
-         (or (not (eql 'skip org-drill-leech-method))
-             (not (org-drill-entry-leech-p)))
-         (or (null item-time)
-             (not (minusp               ; scheduled for today/in future
-                   (- (time-to-days (current-time))
-                      (time-to-days item-time))))))))
+  (cond
+   (*org-drill-cram-mode*
+    (let ((hours (org-drill-hours-since-last-review)))
+      (and (org-drill-entry-p)
+           (or (null hours)
+               (>= hours org-drill-cram-hours)))))
+   (t
+    (let ((item-time (org-get-scheduled-time (point))))
+      (and (org-drill-entry-p)
+           (or (not (eql 'skip org-drill-leech-method))
+               (not (org-drill-entry-leech-p)))
+           (or (null item-time)
+               (not (minusp             ; scheduled for today/in future
+                     (- (time-to-days (current-time))
+                        (time-to-days item-time))))))))))
 
 
 (defun org-drill-entry-new-p ()
@@ -447,8 +528,17 @@ How well did you do? (0-5, ?=help, e=edit, t=tags, q=quit)"
             (org-set-property "DRILL_FAILURE_COUNT"
                               (format "%d" (1+ failures)))
             (if (> (1+ failures) org-drill-leech-failure-threshold)
-                (org-toggle-tag "leech" 'on)))))
+                (org-toggle-tag "leech" 'on))))
+         (t
+          (let ((scheduled-time (org-get-scheduled-time (point))))
+            (when scheduled-time
+              (message "Next review in %d days"
+                       (- (time-to-days scheduled-time)
+                          (time-to-days (current-time))))
+              (sit-for 0.5)))))
         (org-set-property "DRILL_LAST_QUALITY" (format "%d" quality))
+        (org-set-property "DRILL_LAST_REVIEWED"
+                          (time-to-inactive-org-timestamp (current-time)))
         quality))
      ((= ch ?e)
       'edit)
@@ -485,10 +575,13 @@ the current topic."
               (apply 'format
                      (first fmt-and-args)
                      (rest fmt-and-args))
-            (concat "Press any key to see the answer, "
+            (concat "Press key for answer, "
                     "e=edit, t=tags, s=skip, q=quit."))))
     (setq prompt
-          (format "%s %s %s %s"
+          (format "%s %s %s %s %s"
+                  (propertize
+                   (number-to-string (length *org-drill-done-entries*))
+                   'face `(:foreground ,org-drill-done-count-color))
                   (propertize
                    (number-to-string (+ (length *org-drill-again-entries*)
                                         (length *org-drill-failed-entries*)))
@@ -532,24 +625,28 @@ Consider reformulating the item to make it easier to 
remember.\n"
 
 
 (defun org-drill-hide-clozed-text ()
-  (let ((ovl nil))
-    (save-excursion
-      (while (re-search-forward org-drill-cloze-regexp nil t)
-        ;; Don't hide org links, partly because they might contain inline
-        ;; images which we want to keep visible
-        (unless (org-pos-in-regexp (match-beginning 0)
-                                   org-bracket-link-regexp 1)
-          (setf ovl (make-overlay (match-beginning 0) (match-end 0)))
-          (overlay-put ovl 'category
-                       'org-drill-cloze-overlay-defaults)
-          (when (find ?| (match-string 0))
-            (overlay-put ovl
-                         'display
-                         (format "[...%s]"
-                                 (substring-no-properties
-                                  (match-string 0)
-                                  (1+ (position ?| (match-string 0)))
-                                  (1- (length (match-string 0))))))))))))
+  (save-excursion
+    (while (re-search-forward org-drill-cloze-regexp nil t)
+      ;; Don't hide org links, partly because they might contain inline
+      ;; images which we want to keep visible
+      (unless (org-pos-in-regexp (match-beginning 0)
+                                 org-bracket-link-regexp 1)
+        (org-drill-hide-matched-cloze-text)))))
+
+
+(defun org-drill-hide-matched-cloze-text ()
+  "Hide the current match with a 'cloze' visual overlay."
+  (let ((ovl (make-overlay (match-beginning 0) (match-end 0))))
+    (overlay-put ovl 'category
+                 'org-drill-cloze-overlay-defaults)
+    (when (find ?| (match-string 0))
+      (overlay-put ovl
+                   'display
+                   (format "[...%s]"
+                           (substring-no-properties
+                            (match-string 0)
+                            (1+ (position ?| (match-string 0)))
+                            (1- (length (match-string 0)))))))))
 
 
 (defun org-drill-unhide-clozed-text ()
@@ -570,82 +667,112 @@ Consider reformulating the item to make it easier to 
remember.\n"
 ;; recall, nil if they chose to quit.
 
 (defun org-drill-present-simple-card ()
-  (org-drill-hide-all-subheadings-except nil)
-  (org-display-inline-images t)
-  (org-cycle-hide-drawers 'all)
-  (prog1 (org-drill-presentation-prompt)
-    (org-show-subtree)))
+  (with-hidden-cloze-text 
+   (org-drill-hide-all-subheadings-except nil)
+   (org-display-inline-images t)
+   (org-cycle-hide-drawers 'all)
+   (prog1 (org-drill-presentation-prompt)
+     (org-show-subtree))))
 
 
 (defun org-drill-present-two-sided-card ()
-  (let ((drill-sections (org-drill-hide-all-subheadings-except nil)))
-    (when drill-sections
-      (save-excursion
-        (goto-char (nth (random (min 2 (length drill-sections)))
-                        drill-sections))
-        (org-show-subtree)))
-    (org-display-inline-images t)
-    (org-cycle-hide-drawers 'all)
-    (prog1
-        (org-drill-presentation-prompt)
-      (org-show-subtree))))
+  (with-hidden-cloze-text 
+   (let ((drill-sections (org-drill-hide-all-subheadings-except nil)))
+     (when drill-sections
+       (save-excursion
+         (goto-char (nth (random (min 2 (length drill-sections)))
+                         drill-sections))
+         (org-show-subtree)))
+     (org-display-inline-images t)
+     (org-cycle-hide-drawers 'all)
+     (prog1
+         (org-drill-presentation-prompt)
+       (org-show-subtree)))))
 
 
 
 (defun org-drill-present-multi-sided-card ()
-  (let ((drill-sections (org-drill-hide-all-subheadings-except nil)))
-    (when drill-sections
+  (with-hidden-cloze-text 
+   (let ((drill-sections (org-drill-hide-all-subheadings-except nil)))
+     (when drill-sections
+       (save-excursion
+         (goto-char (nth (random (length drill-sections)) drill-sections))
+         (org-show-subtree)))
+     (org-display-inline-images t)    
+     (org-cycle-hide-drawers 'all)
+     (prog1
+         (org-drill-presentation-prompt)
+       (org-show-subtree)))))
+
+
+(defun org-drill-present-multicloze ()
+  (let ((item-end nil)
+        (match-count 0)
+        (body-start (or (cdr (org-get-property-block))
+                        (point))))
+    (org-drill-hide-all-subheadings-except nil)
+    (save-excursion
+      (outline-next-heading)
+      (setq item-end (point)))
+    (save-excursion
+      (goto-char body-start)
+      (while (re-search-forward org-drill-cloze-regexp item-end t)
+        (incf match-count)))
+    (when (plusp match-count)
       (save-excursion
-        (goto-char (nth (random (length drill-sections)) drill-sections))
-        (org-show-subtree)))
-    (org-display-inline-images t)    
+        (goto-char body-start)
+        (re-search-forward org-drill-cloze-regexp
+                           item-end t (1+ (random match-count)))
+        (org-drill-hide-matched-cloze-text)))
+    (org-display-inline-images t)
     (org-cycle-hide-drawers 'all)
-    (prog1
-        (org-drill-presentation-prompt)
-      (org-show-subtree))))
-
-
+    (prog1 (org-drill-presentation-prompt)
+      (org-show-subtree)
+      (org-drill-unhide-clozed-text))))
 
+  
 (defun org-drill-present-spanish-verb ()
   (let ((prompt nil)
         (reveal-headings nil))
-    (case (random 6)
-      (0
-       (org-drill-hide-all-subheadings-except '("Infinitive"))
-       (setq prompt
-             (concat "Translate this Spanish verb, and conjugate it "
-                     "for the *present* tense.")
-             reveal-headings '("English" "Present Tense" "Notes")))
-      (1
-       (org-drill-hide-all-subheadings-except '("English"))
-       (setq prompt (concat "For the *present* tense, conjugate the "
-                            "Spanish translation of this English verb.")
-             reveal-headings '("Infinitive" "Present Tense" "Notes")))
-      (2
-       (org-drill-hide-all-subheadings-except '("Infinitive"))
-       (setq prompt (concat "Translate this Spanish verb, and "
-                            "conjugate it for the *past* tense.")
-             reveal-headings '("English" "Past Tense" "Notes")))
-      (3
-       (org-drill-hide-all-subheadings-except '("English"))
-       (setq prompt (concat "For the *past* tense, conjugate the "
-                            "Spanish translation of this English verb.")
-             reveal-headings '("Infinitive" "Past Tense" "Notes")))
-      (4
-       (org-drill-hide-all-subheadings-except '("Infinitive"))
-       (setq prompt (concat "Translate this Spanish verb, and "
-                            "conjugate it for the *future perfect* tense.")
-             reveal-headings '("English" "Future Perfect Tense" "Notes")))
-      (5
-       (org-drill-hide-all-subheadings-except '("English"))
-       (setq prompt (concat "For the *future perfect* tense, conjugate the "
-                            "Spanish translation of this English verb.")
-             reveal-headings '("Infinitive" "Future Perfect Tense" "Notes"))))
-    (org-cycle-hide-drawers 'all)
-    (prog1
-        (org-drill-presentation-prompt prompt)
-      (org-drill-hide-all-subheadings-except reveal-headings))))
-  
+    (with-hidden-cloze-text 
+     (case (random 6)
+       (0
+        (org-drill-hide-all-subheadings-except '("Infinitive"))
+        (setq prompt
+              (concat "Translate this Spanish verb, and conjugate it "
+                      "for the *present* tense.")
+              reveal-headings '("English" "Present Tense" "Notes")))
+       (1
+        (org-drill-hide-all-subheadings-except '("English"))
+        (setq prompt (concat "For the *present* tense, conjugate the "
+                             "Spanish translation of this English verb.")
+              reveal-headings '("Infinitive" "Present Tense" "Notes")))
+       (2
+        (org-drill-hide-all-subheadings-except '("Infinitive"))
+        (setq prompt (concat "Translate this Spanish verb, and "
+                             "conjugate it for the *past* tense.")
+              reveal-headings '("English" "Past Tense" "Notes")))
+       (3
+        (org-drill-hide-all-subheadings-except '("English"))
+        (setq prompt (concat "For the *past* tense, conjugate the "
+                             "Spanish translation of this English verb.")
+              reveal-headings '("Infinitive" "Past Tense" "Notes")))
+       (4
+        (org-drill-hide-all-subheadings-except '("Infinitive"))
+        (setq prompt (concat "Translate this Spanish verb, and "
+                             "conjugate it for the *future perfect* tense.")
+              reveal-headings '("English" "Future Perfect Tense" "Notes")))
+       (5
+        (org-drill-hide-all-subheadings-except '("English"))
+        (setq prompt (concat "For the *future perfect* tense, conjugate the "
+                             "Spanish translation of this English verb.")
+              reveal-headings '("Infinitive" "Future Perfect Tense" "Notes"))))
+     (org-cycle-hide-drawers 'all)
+     (prog1
+         (org-drill-presentation-prompt prompt)
+       (org-drill-hide-all-subheadings-except reveal-headings)))))
+
+
 
 (defun org-drill-entry ()
   "Present the current topic for interactive review, as in `org-drill'.
@@ -672,11 +799,7 @@ See `org-drill' for more details."
       (let ((presentation-fn (cdr (assoc card-type 
org-drill-card-type-alist))))
         (cond
          (presentation-fn
-          (org-drill-hide-clozed-text)
-          (unwind-protect
-              (progn
-                (setq cont (funcall presentation-fn)))
-            (org-drill-unhide-clozed-text)))
+          (setq cont (funcall presentation-fn)))
          (t
           (error "Unknown card type: '%s'" card-type))))
       
@@ -941,8 +1064,9 @@ agenda-with-archives
                    (cond
                     ((org-drill-entry-new-p)
                      (push (point-marker) *org-drill-new-entries*))
-                    ((<= (org-drill-entry-last-quality)
-                         org-drill-failure-quality)
+                    ((and (org-drill-entry-last-quality)
+                          (<= (org-drill-entry-last-quality)
+                              org-drill-failure-quality))
                      (push (point-marker) *org-drill-failed-entries*))
                     (t
                      (push (point-marker) *org-drill-mature-entries*)))))
@@ -990,15 +1114,21 @@ agenda-with-archives
       (org-drill-final-report)))))
 
 
+(defun org-drill-cram (&optional scope)
+  (interactive)
+  (let ((*org-drill-cram-mode* t))
+    (org-drill scope)))
+
+
 
 (add-hook 'org-mode-hook
           (lambda ()
             (if org-drill-use-visible-cloze-face-p
                 (font-lock-add-keywords
                  'org-mode
-                 `((,org-drill-cloze-regexp
-                    (0 'org-drill-visible-cloze-face nil)))
+                 org-drill-cloze-keywords
                  t))))
 
 
+
 (provide 'org-drill)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]