aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xREADME.html30
-rwxr-xr-xREADME.org19
-rwxr-xr-xorg-drill.el204
3 files changed, 178 insertions, 75 deletions
diff --git a/README.html b/README.html
index a04d8c3..96f0b29 100755
--- a/README.html
+++ b/README.html
@@ -7,7 +7,7 @@ lang="en" xml:lang="en">
<title>Org-Drill</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<meta name="generator" content="Org-mode"/>
-<meta name="generated" content="2011-04-15 08:42:23 "/>
+<meta name="generated" content="2011-04-22 15:27:38 "/>
<meta name="author" content="Paul Sexton"/>
<meta name="description" content=""/>
<meta name="keywords" content=""/>
@@ -249,7 +249,7 @@ recall purposes. For this reason, some other card types are defined, including:
</li>
<li><a href="#sec-4_4">Multi-sided cards</a>
</li>
-<li><a href="#Multicloze-cards">Multicloze cards</a>
+<li><a href="#sec-4_5">Multi-cloze cards</a>
</li>
<li><a href="#sec-4_6">User-defined card types</a>
</li>
@@ -545,15 +545,27 @@ the [North|North/South] Island.
<p>
-However, this is really cumbersome. The 'multicloze' card type exists for this
+However, this is really cumbersome. Multicloze card types exist for this
situation. Multicloze cards behave like 'simple' cards, except that when there
-is more than one area marked as cloze text, only one of the marked areas will
-be hidden during review &ndash; the others all remain visible. The hidden text area
-is chosen randomly at each review.
-</p>
+is more than one area marked as cloze text, some but not all of the areas
+are hidden. There are two types of multicloze card:
+</p>
+<ol>
+<li><code>hide1cloze</code> &ndash; one of the marked areas is hidden during review; the others
+ all remain visible. The hidden text area is chosen randomly at each review.
+ (Note: this type used to be called 'multicloze', and that card type is
+ retained as a synonym for 'hide1cloze'.)
+</li>
+<li><code>show1cloze</code> &ndash; only one of the marked areas is visible during review; all
+ the others are hidden. The hidden text area is chosen randomly at each
+ review.
+</li>
+</ol>
+
+
<p>
So, for the above example, we can actually use the original 'bad' simple card,
-but change its card type to 'multicloze'. Each time the card is presented for
+but change its card type to 'hide1cloze'. Each time the card is presented for
review, one of 'New Zealand', 'Wellington', 'the South Island' or '400,000'
will be hidden.
</p>
@@ -1258,7 +1270,7 @@ or give it different tags or properties, for example.
</div>
</div>
<div id="postamble">
-<p class="date">Date: 2011-04-15 08:42:23 </p>
+<p class="date">Date: 2011-04-22 15:27:38 </p>
<p class="author">Author: Paul Sexton</p>
<p class="creator">Org version 7.5 with Emacs version 23</p>
<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a>
diff --git a/README.org b/README.org
index 491378d..168182b 100755
--- a/README.org
+++ b/README.org
@@ -82,7 +82,7 @@ where you have more control over what information is hidden from the user for
recall purposes. For this reason, some other card types are defined, including:
- [[Two-sided cards]]
- [[Multi-sided cards]]
-- [[Multicloze cards]]
+- [[Multi-cloze cards]]
- [[User-defined card types]]
*A note about comments:* In org mode, comment lines start with '#'. The rest of
@@ -286,14 +286,21 @@ The capital city of New Zealand is Wellington, which is located in
the [North|North/South] Island.
#+END_EXAMPLE
-However, this is really cumbersome. The 'multicloze' card type exists for this
+However, this is really cumbersome. Multicloze card types exist for this
situation. Multicloze cards behave like 'simple' cards, except that when there
-is more than one area marked as cloze text, only one of the marked areas will
-be hidden during review -- the others all remain visible. The hidden text area
-is chosen randomly at each review.
+is more than one area marked as cloze text, some but not all of the areas
+are hidden. There are two types of multicloze card:
+
+1. =hide1cloze= -- one of the marked areas is hidden during review; the others
+ all remain visible. The hidden text area is chosen randomly at each review.
+ (Note: this type used to be called 'multicloze', and that card type is
+ retained as a synonym for 'hide1cloze'.)
+2. =show1cloze= -- only one of the marked areas is visible during review; all
+ the others are hidden. The hidden text area is chosen randomly at each
+ review.
So, for the above example, we can actually use the original 'bad' simple card,
-but change its card type to 'multicloze'. Each time the card is presented for
+but change its card type to 'hide1cloze'. Each time the card is presented for
review, one of 'New Zealand', 'Wellington', 'the South Island' or '400,000'
will be hidden.
diff --git a/org-drill.el b/org-drill.el
index 832afc0..84b4676 100755
--- a/org-drill.el
+++ b/org-drill.el
@@ -201,7 +201,9 @@ 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)
+ ("hide1cloze" . org-drill-present-multicloze-hide1)
+ ("show1cloze" . org-drill-present-multicloze-show1)
+ ("multicloze" . org-drill-present-multicloze-hide1)
("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
@@ -1117,27 +1119,57 @@ How well did you do? (0-5, ?=help, e=edit, t=tags, q=quit)"
nil))))
-(defun org-drill-hide-all-subheadings-except (heading-list)
- "Returns a list containing the position of each immediate subheading of
+;; (defun org-drill-hide-all-subheadings-except (heading-list)
+;; "Returns a list containing the position of each immediate subheading of
+;; the current topic."
+;; (let ((drill-entry-level (org-current-level))
+;; (drill-sections nil)
+;; (drill-heading nil))
+;; (org-show-subtree)
+;; (save-excursion
+;; (org-map-entries
+;; (lambda ()
+;; (when (and (not (outline-invisible-p))
+;; (> (org-current-level) drill-entry-level))
+;; (setq drill-heading (org-get-heading t))
+;; (unless (and (= (org-current-level) (1+ drill-entry-level))
+;; (member drill-heading heading-list))
+;; (hide-subtree))
+;; (push (point) drill-sections)))
+;; "" 'tree))
+;; (reverse drill-sections)))
+
+
+
+(defun org-drill-hide-subheadings-if (test)
+ "TEST is a function taking no arguments. TEST will be called for each
+of the immediate subheadings of the current drill item, with the point
+on the relevant subheading. TEST should return nil if the subheading is
+to be revealed, non-nil if it is to be hidden.
+Returns a list containing the position of each immediate subheading of
the current topic."
(let ((drill-entry-level (org-current-level))
- (drill-sections nil)
- (drill-heading nil))
+ (drill-sections nil))
(org-show-subtree)
(save-excursion
(org-map-entries
(lambda ()
(when (and (not (outline-invisible-p))
(> (org-current-level) drill-entry-level))
- (setq drill-heading (org-get-heading t))
- (unless (and (= (org-current-level) (1+ drill-entry-level))
- (member drill-heading heading-list))
+ (when (or (/= (org-current-level) (1+ drill-entry-level))
+ (funcall test))
(hide-subtree))
(push (point) drill-sections)))
"" 'tree))
(reverse drill-sections)))
+(defun org-drill-hide-all-subheadings-except (heading-list)
+ (org-drill-hide-subheadings-if
+ (lambda () (let ((drill-heading (org-get-heading t)))
+ (not (member drill-heading heading-list))))))
+
+
(defun org-drill-presentation-prompt (&rest fmt-and-args)
(let* ((item-start-time (current-time))
(input nil)
@@ -1289,7 +1321,7 @@ visual overlay."
(org-display-inline-images t)
(org-cycle-hide-drawers 'all)
(prog1 (org-drill-presentation-prompt)
- (org-show-subtree)))))
+ (org-drill-hide-subheadings-if 'org-drill-entry-p)))))
(defun org-drill-present-two-sided-card ()
@@ -1305,7 +1337,7 @@ visual overlay."
(org-cycle-hide-drawers 'all)
(prog1
(org-drill-presentation-prompt)
- (org-show-subtree))))))
+ (org-drill-hide-subheadings-if 'org-drill-entry-p))))))
@@ -1321,10 +1353,12 @@ visual overlay."
(org-cycle-hide-drawers 'all)
(prog1
(org-drill-presentation-prompt)
- (org-show-subtree))))))
+ (org-drill-hide-subheadings-if 'org-drill-entry-p))))))
-(defun org-drill-present-multicloze ()
+(defun org-drill-present-multicloze-hide1 ()
+ "Hides one of the pieces of text that are marked for cloze deletion,
+chosen at random."
(with-hidden-comments
(let ((item-end nil)
(match-count 0)
@@ -1347,7 +1381,40 @@ visual overlay."
(org-display-inline-images t)
(org-cycle-hide-drawers 'all)
(prog1 (org-drill-presentation-prompt)
- (org-show-subtree)
+ (org-drill-hide-subheadings-if 'org-drill-entry-p)
+ (org-drill-unhide-clozed-text)))))
+
+
+(defun org-drill-present-multicloze-show1 ()
+ "Similar to `org-drill-present-multicloze-hide1', but hides all
+the pieces of text that are marked for cloze deletion, except for one
+piece which is chosen at random."
+ (with-hidden-comments
+ (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)
+ (let ((match-to-hide (random match-count)))
+ (save-excursion
+ (goto-char body-start)
+ (dotimes (n match-count)
+ (re-search-forward org-drill-cloze-regexp
+ item-end t)
+ (unless (= n match-to-hide)
+ (org-drill-hide-matched-cloze-text))))))
+ (org-display-inline-images t)
+ (org-cycle-hide-drawers 'all)
+ (prog1 (org-drill-presentation-prompt)
+ (org-drill-hide-subheadings-if 'org-drill-entry-p)
(org-drill-unhide-clozed-text)))))
@@ -1394,6 +1461,22 @@ visual overlay."
(org-drill-hide-all-subheadings-except reveal-headings))))))
+;;; The following macro is necessary because `org-save-outline-visibility'
+;;; currently discards the value returned by its body and returns a garbage
+;;; value instead. (as at org mode v 7.5)
+
+(defmacro org-drill-save-visibility (&rest body)
+ "Store the current visibility state of the org buffer, and restore it
+after executing BODY. Return the value of the last expression
+in BODY."
+ (let ((retval (gensym)))
+ `(let ((,retval nil))
+ (org-save-outline-visibility t
+ (setq ,retval
+ (progn
+ ,@body)))
+ ,retval)))
+
(defun org-drill-entry ()
"Present the current topic for interactive review, as in `org-drill'.
@@ -1414,29 +1497,30 @@ See `org-drill' for more details."
;; (org-back-to-heading))
(let ((card-type (org-entry-get (point) "DRILL_CARD_TYPE"))
(cont nil))
- (save-restriction
- (org-narrow-to-subtree)
- (org-show-subtree)
- (org-cycle-hide-drawers 'all)
-
- (let ((presentation-fn (cdr (assoc card-type org-drill-card-type-alist))))
- (cond
- (presentation-fn
- (setq cont (funcall presentation-fn)))
- (t
- (error "Unknown card type: '%s'" card-type))))
+ (org-drill-save-visibility
+ (save-restriction
+ (org-narrow-to-subtree)
+ (org-show-subtree)
+ (org-cycle-hide-drawers 'all)
- (cond
- ((not cont)
- (message "Quit")
- nil)
- ((eql cont 'edit)
- 'edit)
- ((eql cont 'skip)
- 'skip)
- (t
- (save-excursion
- (org-drill-reschedule)))))))
+ (let ((presentation-fn (cdr (assoc card-type org-drill-card-type-alist))))
+ (cond
+ (presentation-fn
+ (setq cont (funcall presentation-fn)))
+ (t
+ (error "Unknown card type: '%s'" card-type))))
+
+ (cond
+ ((not cont)
+ (message "Quit")
+ nil)
+ ((eql cont 'edit)
+ 'edit)
+ ((eql cont 'skip)
+ 'skip)
+ (t
+ (save-excursion
+ (org-drill-reschedule))))))))
(defun org-drill-entries-pending-p ()
@@ -1730,30 +1814,30 @@ than starting a new one."
(make-string (ceiling cnt 50) ?.)))
(let ((due (org-drill-entry-days-overdue))
(last-int (org-drill-entry-last-interval 1)))
- (cond
- ((not (org-drill-entry-p))
- nil) ; skip
- ((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.
- (push (point-marker) *org-drill-overdue-entries*))
- ((<= (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*)))))
+ (cond
+ ((not (org-drill-entry-p))
+ nil) ; skip
+ ((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.
+ (push (point-marker) *org-drill-overdue-entries*))
+ ((<= (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*)))))
(concat "+" org-drill-question-tag) scope)))
(setq *org-drill-due-entry-count* (org-drill-pending-entry-count))
(setq *org-drill-overdue-entry-count*
@@ -1820,7 +1904,7 @@ exiting them with the `edit' option."
(font-lock-add-keywords
'org-mode
org-drill-cloze-keywords
- t))))
+ nil))))