aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xorg-drill.el198
1 files changed, 104 insertions, 94 deletions
diff --git a/org-drill.el b/org-drill.el
index 793d6b4..b71b1bd 100755
--- a/org-drill.el
+++ b/org-drill.el
@@ -188,11 +188,16 @@ during a drill session."
window t))
+(defvar org-drill-hint-separator "||"
+ "String which, if it occurs within a cloze expression, signifies that the
+rest of the expression after the string is a `hint', to be displayed instead of
+the hidden cloze during a test.")
+
+
(defvar org-drill-cloze-regexp
- ;; ver 1 "[^][]\\(\\[[^][][^]]*\\]\\)"
- ;; ver 2 "\\(\\[.*?\\]\\|^[^[[:cntrl:]]*?\\]\\|\\[.*?$\\)"
- ;; ver 3! "\\(\\[.*?\\]\\|\\[.*?[[:cntrl:]]+.*?\\]\\)"
- "\\(\\[[[:cntrl:][:graph:][:space:]]*?\\)\\(\\||.+?\\)\\(\\]\\)")
+ (concat "\\(\\[[[:cntrl:][:graph:][:space:]]+?\\)\\(\\|"
+ (regexp-quote org-drill-hint-separator)
+ ".+?\\)\\(\\]\\)"))
(defvar org-drill-cloze-keywords
@@ -221,8 +226,7 @@ during a drill session."
("conjugate" org-drill-present-verb-conjugation
org-drill-show-answer-verb-conjugation)
("spanish_verb" . org-drill-present-spanish-verb)
- ("translate_number" org-drill-present-translate-number
- org-drill-show-answer-translate-number))
+ ("translate_number" org-drill-present-translate-number))
"Alist associating card types with presentation functions. Each entry in the
alist takes one of two forms:
1. (CARDTYPE . QUESTION-FN), where CARDTYPE is a string or nil (for default),
@@ -419,6 +423,17 @@ exponential effect on inter-repetition spacing."
:type 'float)
+(defvar drill-answer nil
+ "Global variable that can be bound to a correct answer when an
+item is being presented. If this variable is non-nil, the default
+presentation function will show its value instead of the default
+behaviour of revealing the contents of the drilled item.
+
+This variable is useful for card types that compute their answers
+-- for example, a card type that asks the student to translate a
+random number to another language. ")
+
+
(defvar *org-drill-session-qualities* nil)
(defvar *org-drill-start-time* 0)
(defvar *org-drill-new-entries* nil)
@@ -1472,19 +1487,22 @@ visual overlay, or with the string TEXT if it is supplied."
(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))))
+ (let ((ovl (make-overlay (match-beginning 0) (match-end 0)))
+ (hint-sep-pos (string-match-p (regexp-quote org-drill-hint-separator)
+ (match-string 0))))
(overlay-put ovl 'category
'org-drill-cloze-overlay-defaults)
- (when (find ?| (match-string 0))
+ (when (and hint-sep-pos
+ (> hint-sep-pos 1))
(let ((hint (substring-no-properties
(match-string 0)
- (1+ (position ?| (match-string 0)))
+ (+ hint-sep-pos (length org-drill-hint-separator))
(1- (length (match-string 0))))))
(overlay-put
ovl 'display
;; If hint is like `X...' then display [X...]
;; otherwise display [...X]
- (format (if (string-match-p "\\.\\.\\." hint) "[%s]" "[%s...]")
+ (format (if (string-match-p (regexp-quote "...") hint) "[%s]" "[%s...]")
hint))))))
@@ -1607,7 +1625,7 @@ Note: does not actually alter the item."
;;; Presentation functions ====================================================
-
+;;
;; Each of these is called with point on topic heading. Each needs to show the
;; topic in the form of a 'question' or with some information 'hidden', as
;; appropriate for the card type. The user should then be prompted to press a
@@ -1628,12 +1646,20 @@ Note: does not actually alter the item."
(defun org-drill-present-default-answer (reschedule-fn)
- (org-drill-hide-subheadings-if 'org-drill-entry-p)
- (org-drill-unhide-clozed-text)
- (ignore-errors
- (org-display-inline-images t))
- (with-hidden-cloze-hints
- (funcall reschedule-fn)))
+ (cond
+ (drill-answer
+ (with-replaced-entry-text
+ (format "\nAnswer:\n\n %s\n" drill-answer)
+ (prog1
+ (funcall reschedule-fn)
+ (setq drill-answer nil))))
+ (t
+ (org-drill-hide-subheadings-if 'org-drill-entry-p)
+ (org-drill-unhide-clozed-text)
+ (ignore-errors
+ (org-display-inline-images t))
+ (with-hidden-cloze-hints
+ (funcall reschedule-fn)))))
(defun org-drill-present-two-sided-card ()
@@ -1949,10 +1975,12 @@ pieces rather than one."
(defun org-drill-present-card-using-text (question &optional answer)
- "Present the string QUESTION as the only visible content of the card."
+ "Present the string QUESTION as the only visible content of the card.
+If ANSWER is supplied, set the global variable `drill-answer' to its value."
+ (if answer (setq drill-answer answer))
(with-hidden-comments
(with-replaced-entry-text
- question
+ (concat "\n" question)
(org-drill-hide-all-subheadings-except nil)
(org-cycle-hide-drawers 'all)
(ignore-errors
@@ -1964,7 +1992,9 @@ pieces rather than one."
(defun org-drill-present-card-using-multiple-overlays (replacements &optional answer)
"TEXTS is a list of valid values for the 'display' text property.
Present these overlays, in sequence, as the only
-visible content of the card."
+visible content of the card.
+If ANSWER is supplied, set the global variable `drill-answer' to its value."
+ (if answer (setq drill-answer answer))
(with-hidden-comments
(with-replaced-entry-text-multi
replacements
@@ -1999,6 +2029,7 @@ See `org-drill' for more details."
;; fontification functions in `outline-view-change-hook' can cause big
;; slowdowns, so we temporarily bind this variable to nil here.
(outline-view-change-hook nil))
+ (setq drill-answer nil)
(org-save-outline-visibility t
(save-restriction
(org-narrow-to-subtree)
@@ -2034,6 +2065,7 @@ See `org-drill' for more details."
(defun org-drill-entries-pending-p ()
(or *org-drill-again-entries*
+ *org-drill-current-item*
(and (not (org-drill-maximum-item-count-reached-p))
(not (org-drill-maximum-duration-reached-p))
(or *org-drill-new-entries*
@@ -2045,7 +2077,8 @@ See `org-drill' for more details."
(defun org-drill-pending-entry-count ()
- (+ (length *org-drill-new-entries*)
+ (+ (if (markerp *org-drill-current-item*) 1 0)
+ (length *org-drill-new-entries*)
(length *org-drill-failed-entries*)
(length *org-drill-young-mature-entries*)
(length *org-drill-old-mature-entries*)
@@ -2157,6 +2190,7 @@ RESUMING-P is true if we are resuming a suspended drill session."
(setq end-pos (point-marker))
(return-from org-drill-entries nil))
((eql result 'skip)
+ (setq *org-drill-current-item* nil)
nil) ; skip this item
(t
(cond
@@ -2166,7 +2200,8 @@ RESUMING-P is true if we are resuming a suspended drill session."
(shuffle-list *org-drill-again-entries*)))
(push-end m *org-drill-again-entries*))
(t
- (push m *org-drill-done-entries*))))))))))))
+ (push m *org-drill-done-entries*)))
+ (setq *org-drill-current-item* nil))))))))))
@@ -2448,45 +2483,13 @@ than starting a new one."
(:old
(push (point-marker) *org-drill-old-mature-entries*)))))))
scope)
- ;; (let ((due (org-drill-entry-days-overdue))
- ;; (last-int (org-drill-entry-last-interval 1)))
- ;; (cond
- ;; ((org-drill-entry-empty-p)
- ;; nil) ; skip -- item body is empty
- ;; ((or (null due) ; unscheduled - usually a skipped leech
- ;; (minusp due)) ; scheduled in the future
- ;; (incf *org-drill-dormant-entry-count*)
- ;; (if (eq -1 due)
- ;; (incf *org-drill-due-tomorrow-count*)))
- ;; ((org-drill-entry-new-p)
- ;; (push (point-marker) *org-drill-new-entries*))
- ;; ((<= (org-drill-entry-last-quality 9999)
- ;; org-drill-failure-quality)
- ;; ;; Mature entries that were failed last time are
- ;; ;; FAILED, regardless of how young, old or overdue
- ;; ;; they are.
- ;; (push (point-marker) *org-drill-failed-entries*))
- ;; ((org-drill-entry-overdue-p due last-int)
- ;; ;; Overdue status overrides young versus old
- ;; ;; distinction.
- ;; ;; Store marker + due, for sorting of overdue entries
- ;; (push (cons (point-marker) due) overdue-data))
- ;; ((<= (org-drill-entry-last-interval 9999)
- ;; org-drill-days-before-old)
- ;; ;; Item is 'young'.
- ;; (push (point-marker)
- ;; *org-drill-young-mature-entries*))
- ;; (t
- ;; (push (point-marker)
- ;; *org-drill-old-mature-entries*))))
- ;; Order 'overdue' items so that the most overdue will tend to
- ;; come up for review first, while keeping exact order random
(org-drill-order-overdue-entries overdue-data)
(setq *org-drill-overdue-entry-count*
(length *org-drill-overdue-entries*))))
(setq *org-drill-due-entry-count* (org-drill-pending-entry-count))
(cond
- ((and (null *org-drill-new-entries*)
+ ((and (null *org-drill-current-item*)
+ (null *org-drill-new-entries*)
(null *org-drill-failed-entries*)
(null *org-drill-overdue-entries*)
(null *org-drill-young-mature-entries*)
@@ -2889,13 +2892,17 @@ returns its return value."
;;; `translate_number' card type ==============================================
;;; See spanish.org for usage
-(defvar *drilled-number* 0)
-(defvar *drilled-number-direction* 'to-english)
+
+(defun spelln-integer-in-language (n lang)
+ (let ((spelln-language lang))
+ (spelln-integer-in-words n)))
(defun org-drill-present-translate-number ()
(let ((num-min (read (org-entry-get (point) "DRILL_NUMBER_MIN")))
(num-max (read (org-entry-get (point) "DRILL_NUMBER_MAX")))
(language (read (org-entry-get (point) "DRILL_LANGUAGE" t)))
+ (drilled-number 0)
+ (drilled-number-direction 'to-english)
(highlight-face 'font-lock-warning-face))
(cond
((not (fboundp 'spelln-integer-in-words))
@@ -2908,46 +2915,49 @@ returns its return value."
(if (> num-min num-max)
(psetf num-min num-max
num-max num-min))
- (setq *drilled-number*
+ (setq drilled-number
(+ num-min (random* (abs (1+ (- num-max num-min))))))
- (setq *drilled-number-direction*
+ (setq drilled-number-direction
(if (zerop (random* 2)) 'from-english 'to-english))
- (org-drill-present-card-using-text
- (if (eql 'to-english *drilled-number-direction*)
- (format "\nTranslate into English:\n\n%s\n"
- (let ((spelln-language language))
- (propertize
- (spelln-integer-in-words *drilled-number*)
- 'face highlight-face)))
+ (cond
+ ((eql 'to-english drilled-number-direction)
+ (org-drill-present-card-using-text
+ (format "\nTranslate into English:\n\n%s\n"
+ (propertize
+ (spelln-integer-in-language drilled-number language)
+ 'face highlight-face))
+ (spelln-integer-in-language drilled-number 'english-gb)))
+ (t
+ (org-drill-present-card-using-text
(format "\nTranslate into %s:\n\n%s\n"
(capitalize (format "%s" language))
- (let ((spelln-language 'english-gb))
- (propertize
- (spelln-integer-in-words *drilled-number*)
- 'face highlight-face)))))))))
-
-
-(defun org-drill-show-answer-translate-number (reschedule-fn)
- (let* ((language (read (org-entry-get (point) "DRILL_LANGUAGE" t)))
- (highlight-face 'font-lock-warning-face)
- (non-english
- (let ((spelln-language language))
- (propertize (spelln-integer-in-words *drilled-number*)
- 'face highlight-face)))
- (english
- (let ((spelln-language 'english-gb))
- (propertize (spelln-integer-in-words *drilled-number*)
- 'face 'highlight-face))))
- (with-replaced-entry-text
- (cond
- ((eql 'to-english *drilled-number-direction*)
- (format "\nThe English translation of %s is:\n\n%s\n"
- non-english english))
- (t
- (format "\nThe %s translation of %s is:\n\n%s\n"
- (capitalize (format "%s" language))
- english non-english)))
- (funcall reschedule-fn))))
+ (propertize
+ (spelln-integer-in-language drilled-number 'english-gb)
+ 'face highlight-face))
+ (spelln-integer-in-language drilled-number language))))))))
+
+
+;; (defun org-drill-show-answer-translate-number (reschedule-fn)
+;; (let* ((language (read (org-entry-get (point) "DRILL_LANGUAGE" t)))
+;; (highlight-face 'font-lock-warning-face)
+;; (non-english
+;; (let ((spelln-language language))
+;; (propertize (spelln-integer-in-words *drilled-number*)
+;; 'face highlight-face)))
+;; (english
+;; (let ((spelln-language 'english-gb))
+;; (propertize (spelln-integer-in-words *drilled-number*)
+;; 'face 'highlight-face))))
+;; (with-replaced-entry-text
+;; (cond
+;; ((eql 'to-english *drilled-number-direction*)
+;; (format "\nThe English translation of %s is:\n\n%s\n"
+;; non-english english))
+;; (t
+;; (format "\nThe %s translation of %s is:\n\n%s\n"
+;; (capitalize (format "%s" language))
+;; english non-english)))
+;; (funcall reschedule-fn))))
;;; `spanish_verb' card type ==================================================