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

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

[nongnu] elpa/org-drill b17bf579bd 039/251: - New card types: show2cloze


From: ELPA Syncer
Subject: [nongnu] elpa/org-drill b17bf579bd 039/251: - New card types: show2cloze, hide1_firstmore, show1_firstless, show1_lastmore. See docs for details.
Date: Mon, 17 Jan 2022 18:58:59 -0500 (EST)

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

    - New card types: show2cloze, hide1_firstmore, show1_firstless, 
show1_lastmore. See docs for details.
    - 'conjugate' card type can now show a hint (VERB_INFINITIVE_HINT)
    - New command: org-drill-again: run another drill session using leftover 
items from the last
      session, i.e. don't rescan the item collection.
    - If org-drill-resume is called and there is nothing to resume, offer to 
call org-drill-again
    - Automatically prompt to save all modified buffers when a drill session 
finishes (turn off with
      'org-drill-save-buffers-after-drill-sessions-p')
    - Politely skip cards with unknown card types
    - When suspending a drill session, print a message describing the key that 
runs org-drill-resume
      (it it's bound to a key)
    - org-drill-merge-buffers: can now optionally be prevented from copying 
unmatched items from
      SRC into DEST
    - org-drill-merge-buffers: fixed a bug where it prompted for certain 
property values if they were
      not set in the item being processed
    - org-drill-merge-buffers: ensure that *all* items in DEST are stripped of 
their scheduling data
---
 README.html  | 214 +++++++++++++++-------
 README.org   |  48 ++++-
 org-drill.el | 569 +++++++++++++++++++++++++++++++++++++++++++----------------
 spanish.org  |  62 ++++++-
 4 files changed, 665 insertions(+), 228 deletions(-)

diff --git a/README.html b/README.html
index 5dba098ab7..91836c697a 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-05-12 10:29:29 "/>
+<meta name="generated" content="2011-05-20 23:13:33 NZST"/>
 <meta name="author" content="Paul Sexton"/>
 <meta name="description" content=""/>
 <meta name="keywords" content=""/>
@@ -103,28 +103,30 @@ lang="en" xml:lang="en">
 </ul>
 </li>
 <li><a href="#sec-5">Running the drill session </a></li>
-<li><a href="#sec-6">Cram mode </a></li>
-<li><a href="#sec-7">Leeches </a></li>
-<li><a href="#sec-8">Customisation </a>
+<li><a href="#sec-6">Multiple sequential drill sessions </a></li>
+<li><a href="#sec-7">Cram mode </a></li>
+<li><a href="#sec-8">Leeches </a></li>
+<li><a href="#sec-9">Customisation </a>
 <ul>
-<li><a href="#sec-8_1">Visual appearance of items during drill sessions 
</a></li>
-<li><a href="#sec-8_2">Duration of drill sessions </a></li>
-<li><a href="#sec-8_3">Sources of items for drill sessions (scope) </a></li>
-<li><a href="#sec-8_4">Definition of old and overdue items </a></li>
-<li><a href="#sec-8_5">Spaced repetition algorithm </a>
+<li><a href="#sec-9_1">Visual appearance of items during drill sessions 
</a></li>
+<li><a href="#sec-9_2">Duration of drill sessions </a></li>
+<li><a href="#sec-9_3">Saving buffers after drill sessions </a></li>
+<li><a href="#sec-9_4">Sources of items for drill sessions (scope) </a></li>
+<li><a href="#sec-9_5">Definition of old and overdue items </a></li>
+<li><a href="#sec-9_6">Spaced repetition algorithm </a>
 <ul>
-<li><a href="#sec-8_5_1">Choice of algorithm </a></li>
-<li><a href="#sec-8_5_2">Random variation of repetition intervals </a></li>
-<li><a href="#sec-8_5_3">Adjustment for early or late review of items </a></li>
-<li><a href="#sec-8_5_4">Adjusting item difficulty globally </a></li>
+<li><a href="#sec-9_6_1">Choice of algorithm </a></li>
+<li><a href="#sec-9_6_2">Random variation of repetition intervals </a></li>
+<li><a href="#sec-9_6_3">Adjustment for early or late review of items </a></li>
+<li><a href="#sec-9_6_4">Adjusting item difficulty globally </a></li>
 </ul>
 </li>
-<li><a href="#sec-8_6">Per-file customisation settings </a></li>
+<li><a href="#sec-9_7">Per-file customisation settings </a></li>
 </ul>
 </li>
-<li><a href="#sec-9">Coping with large collections </a></li>
-<li><a href="#sec-10">Sharing, merging and synchronising item collections 
</a></li>
-<li><a href="#sec-11">Incremental reading </a></li>
+<li><a href="#sec-10">Coping with large collections </a></li>
+<li><a href="#sec-11">Sharing, merging and synchronising item collections 
</a></li>
+<li><a href="#sec-12">Incremental reading </a></li>
 </ul>
 </div>
 </div>
@@ -526,7 +528,7 @@ the [North|North/South] Island and has a population of 
about [400,000].
 <p>
 But this card will be difficult to remember. If you get just one of the 4
 hidden facts wrong, you will fail the card. A card like this is likely to
-become a <a href="#sec-7">leech</a>.
+become a <a href="#sec-8">leech</a>.
 </p>
 <p>
 A better way to express all these facts using 'simple' cards is to create
@@ -567,7 +569,7 @@ the [North|North/South] Island.
 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, some but not all of the areas
-are hidden. There are two types of multicloze card:
+can be hidden. There are several types of predefined multicloze card:
 </p>
 <ol>
 <li><code>hide1cloze</code> &ndash; one of the marked areas is hidden during 
review; the others
@@ -579,6 +581,35 @@ are hidden. There are two types of multicloze card:
    the others are hidden. The hidden text area is chosen randomly at each
    review.
 </li>
+<li><code>hide2cloze</code> &ndash; like hide1cloze, but 2 marked pieces of 
text will be hidden,
+   and the rest will be visible.
+</li>
+<li><code>show2cloze</code> &ndash; like show1cloze, but 2 marked pieces of 
text will be visible,
+   the rest are hidden.
+</li>
+</ol>
+
+
+<p>
+There are also some types of multicloze card where some pieces have an
+increased or decreased chance of being hidden. These are intended for use when
+studying languages: generally it is easy to translate a foreign-language
+sentence into your own language if you have met it before, but it is much
+harder to translate in the other direction. Therefore, you will want to test
+the harder direction more often.
+</p><ol>
+<li><code>hide1_firstmore</code> &ndash; only one of the marked pieces of text 
will be
+   hidden. 75% of the time (guaranteed), the <i>first</i> piece is hidden; the 
rest
+   of the time, one of the other pieces is randomly hidden.
+</li>
+<li><code>show1_firstless</code> &ndash; only one of the marked pieces of text 
will be
+   visible. Only 25% of the time (guaranteed) will the <i>first</i> piece will 
be
+   visible; the rest of the time, one of the other pieces is randomly visible.
+</li>
+<li><code>show1_lastmore</code> &ndash; only one of the marked pieces of text 
will be
+   visible. 75% of the time (guaranteed), the <i>last</i> piece will be 
visible;
+   the rest of the time, one of the other pieces is randomly visible.
+</li>
 </ol>
 
 
@@ -683,7 +714,7 @@ drill session, put a brief comment ('# &hellip;')  in the 
item body.
 Start a drill session with <code>M-x org-drill</code>. By default, this 
includes all
 non-hidden topics in the current buffer. <code>org-drill</code> takes an 
optional
 argument, SCOPE, which allows it to take drill items from other
-sources. See <a href="#sec-8_3">below</a> for details.
+sources. See <a href="#sec-9_4">below</a> for details.
 </p>
 <p>
 During a drill session, you will be presented with each item, then asked to
@@ -738,11 +769,35 @@ session.
 </div>
 
 <div id="outline-container-6" class="outline-2">
-<h2 id="sec-6">Cram mode </h2>
+<h2 id="sec-6">Multiple sequential drill sessions </h2>
 <div class="outline-text-2" id="text-6">
 
 
 
+<p>
+Org-Drill has to scan your entire item database each time you start a new drill
+session. This can be slow if you have a large item collection. If you have a
+large number of 'due' items and want to run a second drill session after
+finishing one session, you can use the command <code>org-drill-again</code> to 
run a new
+drill session that draws from the pool of remaining due items that were not
+tested during the previous session, without re-scanning the item collection.
+</p>
+<p>
+Also note that if you run <code>org-drill-resume</code> and you have actually 
finished the
+drill session, you will be asked whether you want to start another drill
+session without re-scanning (as if you had run <code>org-drill-again</code>).
+</p>
+
+</div>
+
+</div>
+
+<div id="outline-container-7" class="outline-2">
+<h2 id="sec-7">Cram mode </h2>
+<div class="outline-text-2" id="text-7">
+
+
+
 <p>
 There are some situations, such as before an exam, where you will want to
 revise all of your cards regardless of when they are next due for review.
@@ -758,9 +813,9 @@ variable <code>org-drill-cram-hours</code>).
 
 </div>
 
-<div id="outline-container-7" class="outline-2">
-<h2 id="sec-7"><a name="leeches" id="leeches"></a>Leeches </h2>
-<div class="outline-text-2" id="text-7">
+<div id="outline-container-8" class="outline-2">
+<h2 id="sec-8"><a name="leeches" id="leeches"></a>Leeches </h2>
+<div class="outline-text-2" id="text-8">
 
 
 <p>
@@ -810,9 +865,9 @@ See <a href="http://www.supermemo.com/help/leech.htm";>the 
SuperMemo website</a>
 
 </div>
 
-<div id="outline-container-8" class="outline-2">
-<h2 id="sec-8">Customisation </h2>
-<div class="outline-text-2" id="text-8">
+<div id="outline-container-9" class="outline-2">
+<h2 id="sec-9">Customisation </h2>
+<div class="outline-text-2" id="text-9">
 
 
 
@@ -825,9 +880,9 @@ settings by adding elisp code to your configuration file 
(<code>.emacs</code>).
 
 </div>
 
-<div id="outline-container-8_1" class="outline-3">
-<h3 id="sec-8_1">Visual appearance of items during drill sessions </h3>
-<div class="outline-text-3" id="text-8_1">
+<div id="outline-container-9_1" class="outline-3">
+<h3 id="sec-9_1">Visual appearance of items during drill sessions </h3>
+<div class="outline-text-3" id="text-9_1">
 
 
 
@@ -861,9 +916,9 @@ invisible while each item is being tested, add:
 
 </div>
 
-<div id="outline-container-8_2" class="outline-3">
-<h3 id="sec-8_2">Duration of drill sessions </h3>
-<div class="outline-text-3" id="text-8_2">
+<div id="outline-container-9_2" class="outline-3">
+<h3 id="sec-9_2">Duration of drill sessions </h3>
+<div class="outline-text-3" id="text-9_2">
 
 
 
@@ -891,9 +946,32 @@ session will not end until <i>all</i> outstanding items 
have been reviewed.
 
 </div>
 
-<div id="outline-container-8_3" class="outline-3">
-<h3 id="sec-8_3"><a name="scope" id="scope"></a>Sources of items for drill 
sessions (scope) </h3>
-<div class="outline-text-3" id="text-8_3">
+<div id="outline-container-9_3" class="outline-3">
+<h3 id="sec-9_3">Saving buffers after drill sessions </h3>
+<div class="outline-text-3" id="text-9_3">
+
+
+
+<p>
+By default, you will be prompted to save all unsaved buffers at the end of a
+drill session. If you don't like this behaviour, use the following setting:
+</p>
+
+
+
+<pre class="example">(setq org-drill-save-buffers-after-drill-sessions-p nil)
+</pre>
+
+
+
+
+</div>
+
+</div>
+
+<div id="outline-container-9_4" class="outline-3">
+<h3 id="sec-9_4"><a name="scope" id="scope"></a>Sources of items for drill 
sessions (scope) </h3>
+<div class="outline-text-3" id="text-9_4">
 
 
 <p>
@@ -934,9 +1012,9 @@ the variable <code>org-drill-scope</code>. Possible values 
are:
 
 </div>
 
-<div id="outline-container-8_4" class="outline-3">
-<h3 id="sec-8_4">Definition of old and overdue items </h3>
-<div class="outline-text-3" id="text-8_4">
+<div id="outline-container-9_5" class="outline-3">
+<h3 id="sec-9_5">Definition of old and overdue items </h3>
+<div class="outline-text-3" id="text-9_5">
 
 
 
@@ -995,18 +1073,18 @@ of 10 days or less. To change this, use the following:
 
 </div>
 
-<div id="outline-container-8_5" class="outline-3">
-<h3 id="sec-8_5">Spaced repetition algorithm </h3>
-<div class="outline-text-3" id="text-8_5">
+<div id="outline-container-9_6" class="outline-3">
+<h3 id="sec-9_6">Spaced repetition algorithm </h3>
+<div class="outline-text-3" id="text-9_6">
 
 
 
 
 </div>
 
-<div id="outline-container-8_5_1" class="outline-4">
-<h4 id="sec-8_5_1">Choice of algorithm </h4>
-<div class="outline-text-4" id="text-8_5_1">
+<div id="outline-container-9_6_1" class="outline-4">
+<h4 id="sec-9_6_1">Choice of algorithm </h4>
+<div class="outline-text-4" id="text-9_6_1">
 
 
 
@@ -1048,9 +1126,9 @@ SuperMemo algorithms. These are:
 
 </div>
 
-<div id="outline-container-8_5_2" class="outline-4">
-<h4 id="sec-8_5_2">Random variation of repetition intervals </h4>
-<div class="outline-text-4" id="text-8_5_2">
+<div id="outline-container-9_6_2" class="outline-4">
+<h4 id="sec-9_6_2">Random variation of repetition intervals </h4>
+<div class="outline-text-4" id="text-9_6_2">
 
 
 
@@ -1084,9 +1162,9 @@ your <code>.emacs</code>:
 
 </div>
 
-<div id="outline-container-8_5_3" class="outline-4">
-<h4 id="sec-8_5_3">Adjustment for early or late review of items </h4>
-<div class="outline-text-4" id="text-8_5_3">
+<div id="outline-container-9_6_3" class="outline-4">
+<h4 id="sec-9_6_3">Adjustment for early or late review of items </h4>
+<div class="outline-text-4" id="text-9_6_3">
 
 
 
@@ -1113,9 +1191,9 @@ effect on the SM2 algorithm.
 
 </div>
 
-<div id="outline-container-8_5_4" class="outline-4">
-<h4 id="sec-8_5_4">Adjusting item difficulty globally </h4>
-<div class="outline-text-4" id="text-8_5_4">
+<div id="outline-container-9_6_4" class="outline-4">
+<h4 id="sec-9_6_4">Adjusting item difficulty globally </h4>
+<div class="outline-text-4" id="text-9_6_4">
 
 
 
@@ -1168,9 +1246,9 @@ To alter the learn fraction, put the following in your 
.emacs:
 
 </div>
 
-<div id="outline-container-8_6" class="outline-3">
-<h3 id="sec-8_6"><a name="per-file-settings" 
id="per-file-settings"></a>Per-file customisation settings </h3>
-<div class="outline-text-3" id="text-8_6">
+<div id="outline-container-9_7" class="outline-3">
+<h3 id="sec-9_7"><a name="per-file-settings" 
id="per-file-settings"></a>Per-file customisation settings </h3>
+<div class="outline-text-3" id="text-9_7">
 
 
 <p>
@@ -1212,9 +1290,9 @@ changes to take effect.
 
 </div>
 
-<div id="outline-container-9" class="outline-2">
-<h2 id="sec-9">Coping with large collections </h2>
-<div class="outline-text-2" id="text-9">
+<div id="outline-container-10" class="outline-2">
+<h2 id="sec-10">Coping with large collections </h2>
+<div class="outline-text-2" id="text-10">
 
 
 
@@ -1231,7 +1309,7 @@ The easiest steps to solve this problem are:
 <li>Divide the file into two or more smaller files.
 </li>
 <li>Within each file, set <code>org-drill-scope</code> to 'directory'. See
-   <a href="#sec-8_6">per-file settings</a> above for instructions about how 
to do this.
+   <a href="#sec-9_7">per-file settings</a> above for instructions about how 
to do this.
 </li>
 </ol>
 
@@ -1239,9 +1317,9 @@ The easiest steps to solve this problem are:
 
 </div>
 
-<div id="outline-container-10" class="outline-2">
-<h2 id="sec-10">Sharing, merging and synchronising item collections </h2>
-<div class="outline-text-2" id="text-10">
+<div id="outline-container-11" class="outline-2">
+<h2 id="sec-11">Sharing, merging and synchronising item collections </h2>
+<div class="outline-text-2" id="text-11">
 
 
 
@@ -1303,9 +1381,9 @@ procedure.
 
 </div>
 
-<div id="outline-container-11" class="outline-2">
-<h2 id="sec-11">Incremental reading </h2>
-<div class="outline-text-2" id="text-11">
+<div id="outline-container-12" class="outline-2">
+<h2 id="sec-12">Incremental reading </h2>
+<div class="outline-text-2" id="text-12">
 
 
 
@@ -1463,7 +1541,7 @@ or give it different tags or properties, for example.
 </div>
 </div>
 <div id="postamble">
-<p class="date">Date: 2011-05-12 10:29:29 </p>
+<p class="date">Date: 2011-05-20 23:13:33 NZST</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 a964532116..e79a208c2c 100755
--- a/README.org
+++ b/README.org
@@ -293,7 +293,7 @@ the [North|North/South] Island.
 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, some but not all of the areas
-are hidden. There are two types of multicloze card:
+can be hidden. There are several types of predefined 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.
@@ -302,6 +302,26 @@ are hidden. There are two types of multicloze card:
 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.
+3. =hide2cloze= -- like hide1cloze, but 2 marked pieces of text will be hidden,
+   and the rest will be visible.
+4. =show2cloze= -- like show1cloze, but 2 marked pieces of text will be 
visible,
+   the rest are hidden.
+
+There are also some types of multicloze card where some pieces have an
+increased or decreased chance of being hidden. These are intended for use when
+studying languages: generally it is easy to translate a foreign-language
+sentence into your own language if you have met it before, but it is much
+harder to translate in the other direction. Therefore, you will want to test
+the harder direction more often.
+5. =hide1_firstmore= -- only one of the marked pieces of text will be
+   hidden. 75% of the time (guaranteed), the /first/ piece is hidden; the rest
+   of the time, one of the other pieces is randomly hidden.
+6. =show1_firstless= -- only one of the marked pieces of text will be
+   visible. Only 25% of the time (guaranteed) will the /first/ piece will be
+   visible; the rest of the time, one of the other pieces is randomly visible.
+7. =show1_lastmore= -- only one of the marked pieces of text will be
+   visible. 75% of the time (guaranteed), the /last/ piece will be visible;
+   the rest of the time, one of the other pieces is randomly visible.
 
 So, for the above example, we can actually use the original 'bad' simple card,
 but change its card type to 'hide1cloze'. Each time the card is presented for
@@ -402,6 +422,21 @@ successfully resuming the session. In that case you will 
need to start a new
 session.
 
 
+* Multiple sequential drill sessions
+
+
+Org-Drill has to scan your entire item database each time you start a new drill
+session. This can be slow if you have a large item collection. If you have a
+large number of 'due' items and want to run a second drill session after
+finishing one session, you can use the command =org-drill-again= to run a new
+drill session that draws from the pool of remaining due items that were not
+tested during the previous session, without re-scanning the item collection.
+
+Also note that if you run =org-drill-resume= and you have actually finished the
+drill session, you will be asked whether you want to start another drill
+session without re-scanning (as if you had run =org-drill-again=).
+
+
 * Cram mode
 
 
@@ -491,6 +526,17 @@ will not count as reasons to end the session. If both 
variables are nil, the
 session will not end until /all/ outstanding items have been reviewed.
 
 
+** Saving buffers after drill sessions
+
+
+By default, you will be prompted to save all unsaved buffers at the end of a
+drill session. If you don't like this behaviour, use the following setting:
+
+#+BEGIN_EXAMPLE
+(setq org-drill-save-buffers-after-drill-sessions-p nil)
+#+END_EXAMPLE
+
+
 ** Sources of items for drill sessions (scope)
 # <<scope>>
 
diff --git a/org-drill.el b/org-drill.el
index 599edf86e4..96763abcc4 100755
--- a/org-drill.el
+++ b/org-drill.el
@@ -1,7 +1,7 @@
 ;;; org-drill.el - Self-testing using spaced repetition
 ;;;
 ;;; Author: Paul Sexton <eeeickythump@gmail.com>
-;;; Version: 2.3
+;;; Version: 2.3.2
 ;;; Repository at http://bitbucket.org/eeeickythump/org-drill/
 ;;;
 ;;;
@@ -210,7 +210,11 @@ during a drill session."
     ("hide1cloze" . org-drill-present-multicloze-hide1)
     ("hide2cloze" . org-drill-present-multicloze-hide2)
     ("show1cloze" . org-drill-present-multicloze-show1)
+    ("show2cloze" . org-drill-present-multicloze-show2)
     ("multicloze" . org-drill-present-multicloze-hide1)
+    ("hide1_firstmore" . org-drill-present-multicloze-hide1-firstmore)
+    ("show1_lastmore" . org-drill-present-multicloze-show1-lastmore)
+    ("show1_firstless" . org-drill-present-multicloze-show1-firstless)
     ("conjugate" org-drill-present-verb-conjugation
      org-drill-show-answer-verb-conjugation)
     ("spanish_verb" . org-drill-present-spanish-verb)
@@ -261,6 +265,14 @@ directory            All files with the extension '.org' 
in the same
                  list))
 
 
+(defcustom org-drill-save-buffers-after-drill-sessions-p
+  t
+  "If non-nil, prompt to save all modified buffers after a drill session
+finishes."
+  :group 'org-drill
+  :type 'boolean)
+
+
 (defcustom org-drill-spaced-repetition-algorithm
   'sm5
   "Which SuperMemo spaced repetition algorithm to use for scheduling items.
@@ -381,7 +393,6 @@ exponential effect on inter-repetition spacing."
 (defvar *org-drill-due-entry-count* 0)
 (defvar *org-drill-overdue-entry-count* 0)
 (defvar *org-drill-due-tomorrow-count* 0)
-(defvar *org-drill-current-entry-schedule-type* nil)
 (defvar *org-drill-overdue-entries* nil
   "List of markers for items that are considered 'overdue', based on
 the value of ORG-DRILL-OVERDUE-INTERVAL-FACTOR.")
@@ -431,6 +442,7 @@ for review unless they were already reviewed in the recent 
past?")
 (put 'org-drill-overdue-interval-factor 'safe-local-variable 'floatp)
 (put 'org-drill-scope 'safe-local-variable
      '(lambda (val) (or (symbolp val) (listp val))))
+(put 'org-drill-save-buffers-after-drill-sessions-p 'safe-local-variable 
'booleanp)
 
 
 ;;;; Utilities ================================================================
@@ -479,6 +491,13 @@ Example: (round-float 3.56755765 3) -> 3.568"
     (/ (float (round (* floatnum n))) n)))
 
 
+(defun command-keybinding-to-string (cmd)
+  "Return a human-readable description of the key/keys to which the command
+CMD is bound, or nil if it is not bound to a key."
+  (let ((key (where-is-internal cmd overriding-local-map t)))
+    (if key (key-description key))))
+
+
 (defun time-to-inactive-org-timestamp (time)
   (format-time-string
    (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")
@@ -1276,6 +1295,7 @@ the current topic."
          (mature-entry-count (+ (length *org-drill-young-mature-entries*)
                                 (length *org-drill-old-mature-entries*)
                                 (length *org-drill-overdue-entries*)))
+         (status (first (org-drill-entry-status)))
          (prompt
           (if fmt-and-args
               (apply 'format
@@ -1287,13 +1307,14 @@ the current topic."
           (format "%s %s %s %s %s %s"
                   (propertize
                    (char-to-string
-                    (case *org-drill-current-entry-schedule-type*
-                      (new ?N) (young ?Y) (old ?o) (overdue ?!) (failed ?F) (t 
??)))
+                    (case status
+                      (:new ?N) (:young ?Y) (:old ?o) (:overdue ?!)
+                      (:failed ?F) (t ??)))
                    'face `(:foreground
-                           ,(case *org-drill-current-entry-schedule-type*
-                              (new org-drill-new-count-color)
-                              ((young old) org-drill-mature-count-color)
-                              ((overdue failed) org-drill-failed-count-color)
+                           ,(case status
+                              (:new org-drill-new-count-color)
+                              ((:young :old) org-drill-mature-count-color)
+                              ((:overdue :failed) org-drill-failed-count-color)
                               (t org-drill-done-count-color))))
                   (propertize
                    (number-to-string (length *org-drill-done-entries*))
@@ -1547,15 +1568,30 @@ Note: does not actually alter the item."
          (org-drill-hide-subheadings-if 'org-drill-entry-p)))))))
 
 
-(defun org-drill-present-multicloze-hide-n (number-to-hide)
+(defun org-drill-present-multicloze-hide-n (number-to-hide
+                                            &optional
+                                            force-show-first
+                                            force-show-last
+                                            force-hide-first)
   "Hides NUMBER-TO-HIDE pieces of text that are marked for cloze deletion,
-chosen at random."
+chosen at random.
+If NUMBER-TO-HIDE is negative, show only (ABS NUMBER-TO-HIDE) pieces,
+hiding all the rest.
+If FORCE-HIDE-FIRST is non-nil, force the first piece of text to be one of
+the hidden items.
+If FORCE-SHOW-FIRST is non-nil, never hide the first piece of text.
+If FORCE-SHOW-LAST is non-nil, never hide the last piece of text.
+If the number of text pieces in the item is less than
+NUMBER-TO-HIDE, then all text pieces will be hidden (except the first or last
+items if FORCE-SHOW-FIRST or FORCE-SHOW-LAST is non-nil)."
   (with-hidden-comments
    (with-hidden-cloze-hints
     (let ((item-end nil)
           (match-count 0)
           (body-start (or (cdr (org-get-property-block))
                           (point))))
+      (if (and force-hide-first force-show-first)
+          (error "FORCE-HIDE-FIRST and FORCE-SHOW-FIRST are mutually 
exclusive"))
       (org-drill-hide-all-subheadings-except nil)
       (save-excursion
         (outline-next-heading)
@@ -1564,10 +1600,24 @@ chosen at random."
         (goto-char body-start)
         (while (re-search-forward org-drill-cloze-regexp item-end t)
           (incf match-count)))
+      (if (minusp number-to-hide)
+          (setq number-to-hide (+ match-count number-to-hide)))
       (when (plusp match-count)
-        (let ((match-nums (subseq (shuffle-list (loop for i from 1 to 
match-count
-                                                      collect i))
-                                  0 number-to-hide)))
+        (let* ((positions (shuffle-list (loop for i from 1
+                                              to match-count
+                                              collect i)))
+               (match-nums nil))
+          (if force-hide-first
+              ;; Force '1' to be in the list, and to be the first item
+              ;; in the list.
+              (setq positions (cons 1 (remove 1 positions))))
+          (if force-show-first
+              (setq positions (remove 1 positions)))
+          (if force-show-last
+              (setq positions (remove match-count positions)))
+          (setq match-nums
+                (subseq positions
+                        0 (min number-to-hide (length positions))))
           (dolist (pos-to-hide match-nums)
             (save-excursion
               (goto-char body-start)
@@ -1593,39 +1643,10 @@ chosen at random."
   (org-drill-present-multicloze-hide-n 2))
 
 
-;; (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)
-;;          (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 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-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."
+(defun org-drill-present-multicloze-hide-nth (cnt)
+  "Hide the CNT'th piece of clozed text. 1 is the first piece. If
+CNT is negative, count backwards, so -1 means the last item, -2
+the second to last, etc."
   (with-hidden-comments
    (with-hidden-cloze-hints
     (let ((item-end nil)
@@ -1640,15 +1661,17 @@ piece which is chosen at random."
         (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))))))
+      (cond
+       ((or (not (plusp match-count))
+            (> cnt match-count)
+            (and (minusp cnt) (> (abs cnt) match-count)))
+        nil)
+       (t
+        (save-excursion
+          (goto-char body-start)
+          (re-search-forward org-drill-cloze-regexp
+                             item-end t (if (minusp cnt) (+ 1 cnt match-count) 
cnt))
+          (org-drill-hide-matched-cloze-text))))
       (org-display-inline-images t)
       (org-cycle-hide-drawers 'all)
       (prog1 (org-drill-presentation-prompt)
@@ -1656,6 +1679,106 @@ piece which is chosen at random."
         (org-drill-unhide-clozed-text))))))
 
 
+(defun org-drill-present-multicloze-hide-first ()
+  "Hides the first piece of text that is marked for cloze deletion."
+  (org-drill-present-multicloze-hide-nth 1))
+
+
+(defun org-drill-present-multicloze-hide-last ()
+  "Hides the last piece of text that is marked for cloze deletion."
+  (org-drill-present-multicloze-hide-nth -1))
+
+
+(defun org-drill-present-multicloze-hide1-firstmore ()
+  "Three out of every four repetitions, hides the FIRST piece of
+text that is marked for cloze deletion. One out of every four
+repetitions, hide one of the other pieces of text, chosen at
+random."
+  ;; The 'firstmore' and 'lastmore' functions used to randomly choose whether
+  ;; to hide the 'favoured' piece of text. However even when the chance of
+  ;; hiding it was set quite high (80%), the outcome was too unpredictable over
+  ;; the small number of repetitions where most learning takes place for each
+  ;; item. In other words, the actual frequency during the first 10 repetitions
+  ;; was often very different from 80%. Hence we use modulo instead.
+  (if (zerop (mod (1+ (org-drill-entry-total-repeats 0)) 4))
+      ;; 25% of time, hide any item except the first
+      (org-drill-present-multicloze-hide-n 1 t)
+    ;; 75% of time, hide first item
+    (org-drill-present-multicloze-hide-first)))
+
+
+(defun org-drill-present-multicloze-show1-lastmore ()
+  "Three out of every four repetitions, hides all pieces except
+the last. One out of every four repetitions, shows any random
+piece. The effect is similar to 'show1cloze' except that the last
+item is much less likely to be the item that is visible."
+  (if (zerop (mod (1+ (org-drill-entry-total-repeats 0)) 4))
+      ;; 25% of time, show any item except the last
+      (org-drill-present-multicloze-hide-n -1 nil t)
+    ;; 75% of time, show the LAST item
+    (org-drill-present-multicloze-hide-n -1 nil t)))
+
+
+(defun org-drill-present-multicloze-show1-firstless ()
+  "Three out of every four repetitions, hides all pieces except
+one, where the shown piece is guaranteed NOT to be the first
+piece. One out of every four repetitions, shows any random
+piece. The effect is similar to 'show1cloze' except that the
+first item is much less likely to be the item that is visible."
+  (if (zerop (mod (1+ (org-drill-entry-total-repeats 0)) 4))
+      ;; 25% of time, show the first item
+      (org-drill-present-multicloze-hide-n -1 t)
+    ;; 75% of time, show any item, except the first
+    (org-drill-present-multicloze-hide-n -1 nil nil t)))
+
+
+(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."
+  (org-drill-present-multicloze-hide-n -1))
+
+
+(defun org-drill-present-multicloze-show2 ()
+  "Similar to `org-drill-present-multicloze-show1', but reveals two
+pieces rather than one."
+  (org-drill-present-multicloze-hide-n -2))
+
+
+;; (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
+;;    (with-hidden-cloze-hints
+;;     (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))))))
+
+
 (defun org-drill-present-card-using-text (question &optional answer)
   "Present the string QUESTION as the only visible content of the card."
   (with-hidden-comments
@@ -1716,23 +1839,25 @@ See `org-drill' for more details."
                                   'org-drill-present-default-answer)
                     presentation-fn (first presentation-fn)))
          (cond
-          (presentation-fn
-           (setq cont (funcall presentation-fn)))
+          ((null presentation-fn)
+           (message "%s:%d: Unrecognised card type '%s', skipping..."
+                    (buffer-name) (point) card-type)
+           (sit-for 0.5)
+           'skip)
           (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
-           (funcall answer-fn
-                    (lambda () (org-drill-reschedule))))))))))
+           (setq cont (funcall presentation-fn))
+           (cond
+            ((not cont)
+             (message "Quit")
+             nil)
+            ((eql cont 'edit)
+             'edit)
+            ((eql cont 'skip)
+             'skip)
+            (t
+             (save-excursion
+               (funcall answer-fn
+                        (lambda () (org-drill-reschedule)))))))))))))
 
 
 (defun org-drill-entries-pending-p ()
@@ -1785,7 +1910,6 @@ maximum number of items."
           ((and *org-drill-failed-entries*
                 (not (org-drill-maximum-item-count-reached-p))
                 (not (org-drill-maximum-duration-reached-p)))
-           (setq *org-drill-current-entry-schedule-type* 'failed)
            (pop-random *org-drill-failed-entries*))
           ;; Next priority is overdue items.
           ((and *org-drill-overdue-entries*
@@ -1794,13 +1918,11 @@ maximum number of items."
            ;; We use `pop', not `pop-random', because we have already
            ;; sorted overdue items into a random order which takes
            ;; number of days overdue into account.
-           (setq *org-drill-current-entry-schedule-type* 'overdue)
            (pop *org-drill-overdue-entries*))
           ;; Next priority is 'young' items.
           ((and *org-drill-young-mature-entries*
                 (not (org-drill-maximum-item-count-reached-p))
                 (not (org-drill-maximum-duration-reached-p)))
-           (setq *org-drill-current-entry-schedule-type* 'young)
            (pop-random *org-drill-young-mature-entries*))
           ;; Next priority is newly added items, and older entries.
           ;; We pool these into a single group.
@@ -1812,15 +1934,12 @@ maximum number of items."
             ((< (random* (+ (length *org-drill-new-entries*)
                             (length *org-drill-old-mature-entries*)))
                 (length *org-drill-new-entries*))
-             (setq *org-drill-current-entry-schedule-type* 'new)
              (pop-random *org-drill-new-entries*))
             (t
-             (setq *org-drill-current-entry-schedule-type* 'old)
              (pop-random *org-drill-old-mature-entries*))))
           ;; After all the above are done, last priority is items
           ;; that were failed earlier THIS SESSION.
           (*org-drill-again-entries*
-           (setq *org-drill-current-entry-schedule-type* 'failed)
            (pop *org-drill-again-entries*))
           (t                            ; nothing left -- return nil
            (return-from org-drill-pop-next-pending-entry nil)))))
@@ -1847,26 +1966,35 @@ RESUMING-P is true if we are resuming a suspended drill 
session."
           (error "Unexpectedly ran out of pending drill items"))
         (save-excursion
           (org-drill-goto-entry m)
-          (setq result (org-drill-entry))
           (cond
-           ((null result)
-            (message "Quit")
-            (setq end-pos :quit)
-            (return-from org-drill-entries nil))
-           ((eql result 'edit)
-            (setq end-pos (point-marker))
-            (return-from org-drill-entries nil))
-           ((eql result 'skip)
-            nil)                        ; skip this item
+           ((not (org-drill-entry-due-p))
+            ;; The entry is not due anymore. This could arise if the user
+            ;; suspends a drill session, then drills an individual entry,
+            ;; then resumes the session.
+            (message "Entry no longer due, skipping...")
+            (sit-for 0.3)
+            nil)
            (t
+            (setq result (org-drill-entry))
             (cond
-             ((<= result org-drill-failure-quality)
-              (if *org-drill-again-entries*
-                  (setq *org-drill-again-entries*
-                        (shuffle-list *org-drill-again-entries*)))
-              (push-end m *org-drill-again-entries*))
+             ((null result)
+              (message "Quit")
+              (setq end-pos :quit)
+              (return-from org-drill-entries nil))
+             ((eql result 'edit)
+              (setq end-pos (point-marker))
+              (return-from org-drill-entries nil))
+             ((eql result 'skip)
+              nil)                      ; skip this item
              (t
-              (push m *org-drill-done-entries*))))))))))
+              (cond
+               ((<= result org-drill-failure-quality)
+                (if *org-drill-again-entries*
+                    (setq *org-drill-again-entries*
+                          (shuffle-list *org-drill-again-entries*)))
+                (push-end m *org-drill-again-entries*))
+               (t
+                (push m *org-drill-done-entries*))))))))))))
 
 
 
@@ -1961,14 +2089,19 @@ order to make items appear more frequently over time."
 
 
 
-(defun org-drill-free-all-markers ()
-  (dolist (m (append  *org-drill-done-entries*
-                      *org-drill-new-entries*
-                      *org-drill-failed-entries*
-                      *org-drill-again-entries*
-                      *org-drill-overdue-entries*
-                      *org-drill-young-mature-entries*
-                      *org-drill-old-mature-entries*))
+(defun org-drill-free-markers (markers)
+  "MARKERS is a list of markers, all of which will be freed (set to
+point nowhere). Alternatively, MARKERS can be 't', in which case
+all the markers used by Org-Drill will be freed."
+  (dolist (m (if (eql t markers)
+                 (append  *org-drill-done-entries*
+                          *org-drill-new-entries*
+                          *org-drill-failed-entries*
+                          *org-drill-again-entries*
+                          *org-drill-overdue-entries*
+                          *org-drill-young-mature-entries*
+                          *org-drill-old-mature-entries*)
+               markers))
     (free-marker m)))
 
 
@@ -1979,6 +2112,58 @@ order to make items appear more frequently over time."
                       (lambda (a b) (> (cdr a) (cdr b)))))))
 
 
+(defun org-drill-entry-status ()
+  "Returns a list (STATUS DUE) where DUE is the number of days overdue,
+zero being due today, -1 being scheduled 1 day in the future. STATUS is
+one of the following values:
+- nil, if the item is not a drill entry, or has an empty body
+- :unscheduled
+- :future
+- :new
+- :failed
+- :overdue
+- :young
+- :old
+"
+  (save-excursion
+    (unless (org-at-heading-p)
+      (org-back-to-heading))
+    (let ((due (org-drill-entry-days-overdue))
+          (last-int (org-drill-entry-last-interval 1)))
+      (list
+       (cond
+        ((not (org-drill-entry-p))
+         nil)
+        ((org-drill-entry-empty-p)
+         nil)                           ; skip -- item body is empty
+        ((null due)                     ; unscheduled - usually a skipped leech
+         :unscheduled)
+        ;; ((eql -1 due)
+        ;;  :tomorrow)
+        ((minusp due)                   ; scheduled in the future
+         :future)
+        ;; The rest of the stati all denote 'due' items 
==========================
+        ((<= (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.
+         :failed)
+        ((org-drill-entry-new-p)
+         :new)
+        ((org-drill-entry-overdue-p due last-int)
+         ;; Overdue status overrides young versus old
+         ;; distinction.
+         ;; Store marker + due, for sorting of overdue entries
+         :overdue)
+        ((<= (org-drill-entry-last-interval 9999)
+             org-drill-days-before-old)
+         :young)
+        (t
+         :old))
+       due))))
+
+
 (defun org-drill (&optional scope resume-p)
   "Begin an interactive 'drill session'. The user is asked to
 review a series of topics (headers). Each topic is initially
@@ -2016,7 +2201,7 @@ than starting a new one."
         (cnt 0))
     (block org-drill
       (unless resume-p
-        (org-drill-free-all-markers)
+        (org-drill-free-markers t)
         (setq *org-drill-current-item* nil
               *org-drill-done-entries* nil
               *org-drill-dormant-entry-count* 0
@@ -2058,38 +2243,59 @@ than starting a new one."
                        (sit-for 0.5)
                        (setq warned-about-id-creation t))
                      (org-id-get-create) ; ensure drill entry has unique ID
-                     (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*)))))))
+                     (destructuring-bind (status due) (org-drill-entry-status)
+                       (case status
+                         (:unscheduled
+                          (incf *org-drill-dormant-entry-count*))
+                         ;; (:tomorrow
+                         ;;  (incf *org-drill-dormant-entry-count*)
+                         ;;  (incf *org-drill-due-tomorrow-count*))
+                         (:future
+                          (incf *org-drill-dormant-entry-count*)
+                          (if (eq -1 due)
+                              (incf *org-drill-due-tomorrow-count*)))
+                         (:new
+                          (push (point-marker) *org-drill-new-entries*))
+                         (:failed
+                          (push (point-marker) *org-drill-failed-entries*))
+                         (:young
+                          (push (point-marker) 
*org-drill-young-mature-entries*))
+                         (:overdue
+                          (push (cons (point-marker) due) overdue-data))
+                         (: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)
@@ -2108,21 +2314,25 @@ than starting a new one."
               (message "Drill session finished!"))))
         (progn
           (unless end-pos
-            (org-drill-free-all-markers)))))
+            (org-drill-free-markers *org-drill-done-entries*)))))
     (cond
      (end-pos
       (when (markerp end-pos)
         (org-drill-goto-entry end-pos))
-      (message
-       "You can continue the drill session with `M-x org-drill-resume'."))
+      (let ((keystr (command-keybinding-to-string 'org-drill-resume)))
+        (message
+         "You can continue the drill session with the command 
`org-drill-resume'.%s"
+         (if keystr (format "\nYou can run this command by pressing %s." 
keystr)
+           ""))))
      (t
       (org-drill-final-report)
       (if (eql 'sm5 org-drill-spaced-repetition-algorithm)
           (org-drill-save-optimal-factor-matrix))
+      (if org-drill-save-buffers-after-drill-sessions-p
+          (save-some-buffers))
       ))))
 
 
-
 (defun org-drill-save-optimal-factor-matrix ()
   (message "Saving optimal factor matrix...")
   (customize-save-variable 'org-drill-optimal-factor-matrix
@@ -2153,11 +2363,43 @@ files in the same directory as the current file."
   (org-drill 'directory))
 
 
+(defun org-drill-again (&optional scope)
+  "Run a new drill session, but try to use leftover due items that
+were not reviewed during the last session, rather than scanning for
+unreviewed items. If there are no leftover items in memory, a full
+scan will be performed."
+  (interactive)
+  (cond
+   ((plusp (org-drill-pending-entry-count))
+    (org-drill-free-markers *org-drill-done-entries*)
+    (if (markerp *org-drill-current-item*)
+        (free-marker *org-drill-current-item*))
+    (setq *org-drill-start-time* (float-time (current-time))
+          *org-drill-done-entries* nil
+          *org-drill-current-item* nil)
+    (org-drill scope t))
+   (t
+    (org-drill scope))))
+
+
+
 (defun org-drill-resume ()
   "Resume a suspended drill session. Sessions are suspended by
-exiting them with the `edit' option."
+exiting them with the `edit' or `quit' options."
   (interactive)
-  (org-drill nil t))
+  (cond
+   ((org-drill-entries-pending-p)
+    (org-drill nil t))
+   ((and (plusp (org-drill-pending-entry-count))
+         ;; Current drill session is finished, but there are still
+         ;; more items which need to be reviewed.
+         (y-or-n-p (format
+                    "You have finished the drill session. However, %d items 
still
+need reviewing. Start a new drill session? "
+                    (org-drill-pending-entry-count))))
+    (org-drill-again))
+   (t
+    (message "You have finished the drill session."))))
 
 
 (defun org-drill-strip-entry-data ()
@@ -2249,13 +2491,20 @@ the tag 'imported'."
 
 
 
-(defun org-drill-merge-buffers (src &optional dest)
+(defun org-drill-merge-buffers (src &optional dest ignore-new-items-p)
   "SRC and DEST are two org mode buffers containing drill items.
 For each drill item in DEST that shares an ID with an item in SRC,
 overwrite scheduling data in DEST with data taken from the item in SRC.
 This is intended for use when two people are sharing a set of drill items,
 one person has made some updates to the item set, and the other person
-wants to migrate to the updated set without losing their scheduling data."
+wants to migrate to the updated set without losing their scheduling data.
+
+By default, any drill items in SRC which do not exist in DEST are
+copied into DEST. We attempt to place the copied item in the
+equivalent location in DEST to its location in SRC, by matching
+the heading hierarchy. However if IGNORE-NEW-ITEMS-P is non-nil,
+we simply ignore any items that do not exist in DEST, and do not
+copy them across."
   ;; In future could look at what to do if we find an item in SRC whose ID
   ;; is not present in DEST -- copy the whole item to DEST?
   ;; org-copy-subtree --> org-paste-subtree
@@ -2309,17 +2558,32 @@ wants to migrate to the updated set without losing 
their scheduling data."
                    (unless (zerop total-repeats)
                      (org-drill-store-item-data last-interval repetitions 
failures
                                                 total-repeats meanq ease)
-                     (org-set-property "LAST_QUALITY" last-quality)
-                     (org-set-property "LAST_REVIEWED" last-reviewed)
+                     (if last-quality
+                         (org-set-property "LAST_QUALITY" last-quality)
+                       (org-delete-property "LAST_QUALITY"))
+                     (if last-reviewed
+                         (org-set-property "LAST_REVIEWED" last-reviewed)
+                       (org-delete-property "LAST_REVIEWED"))
                      (if scheduled-time
                          (org-schedule nil scheduled-time)))))
+               (remhash id *org-drill-dest-id-table*)
                (free-marker marker)))
             (t
              ;; item in SRC has ID, but no matching ID in DEST.
              ;; It must be a new item that does not exist in DEST.
              ;; Copy the entire item to the *end* of DEST.
-             (org-drill-copy-entry-to-other-buffer dest)))))
-       'file))))
+             (unless ignore-new-items-p
+               (org-drill-copy-entry-to-other-buffer dest))))))
+       'file))
+    ;; Finally: there may be some items in DEST which are not in SRC, and
+    ;; which have been scheduled by another user of DEST. Clear out the
+    ;; scheduling info from all the unmatched items in DEST.
+    (with-current-buffer dest
+      (maphash (lambda (id m)
+                 (goto-char m)
+                 (org-drill-strip-entry-data)
+                 (free-marker m))
+               *org-drill-dest-id-table*))))
 
 
 
@@ -2357,6 +2621,7 @@ the name of the tense.")
   "Auxiliary function used by `org-drill-present-verb-conjugation' and
 `org-drill-show-answer-verb-conjugation'."
   (let ((infinitive (org-entry-get (point) "VERB_INFINITIVE" t))
+        (inf-hint (org-entry-get (point) "VERB_INFINITIVE_HINT" t))
         (translation (org-entry-get (point) "VERB_TRANSLATION" t))
         (tense (org-entry-get (point) "VERB_TENSE" nil))
         (highlight-face nil))
@@ -2365,6 +2630,7 @@ the name of the tense.")
              infinitive translation tense (point)))
     (setq tense (downcase (car (read-from-string tense)))
           infinitive (car (read-from-string infinitive))
+          inf-hint (if inf-hint (car (read-from-string inf-hint)))
           translation (car (read-from-string translation)))
     (setq highlight-face
           (list :foreground
@@ -2373,12 +2639,12 @@ the name of the tense.")
     (setq infinitive (propertize infinitive 'face highlight-face))
     (setq translation (propertize translation 'face highlight-face))
     (setq tense (propertize tense 'face highlight-face))
-    (list infinitive translation tense)))
+    (list infinitive inf-hint translation tense)))
 
 
 (defun org-drill-present-verb-conjugation ()
   "Present a drill entry whose card type is 'conjugate'."
-  (destructuring-bind (infinitive translation tense)
+  (destructuring-bind (infinitive inf-hint translation tense)
       (org-drill-get-verb-conjugation-info)
     (org-drill-present-card-using-text
      (cond
@@ -2386,15 +2652,18 @@ the name of the tense.")
        (format "\nTranslate the verb\n\n%s\n\nand conjugate for the %s 
tense.\n\n"
                infinitive tense))
       (t
-       (format "\nGive the verb that means\n\n%s\n\nand conjugate for the %s 
tense.\n\n"
-               translation tense))))))
+       (format "\nGive the verb that means\n\n%s %s\n
+and conjugate for the %s tense.\n\n"
+               translation
+               (if inf-hint (format "  [HINT: %s]" inf-hint) "")
+               tense))))))
 
 
 (defun org-drill-show-answer-verb-conjugation (reschedule-fn)
   "Show the answer for a drill item whose card type is 'conjugate'.
 RESCHEDULE-FN must be a function that calls `org-drill-reschedule' and
 returns its return value."
-  (destructuring-bind (infinitive translation tense)
+  (destructuring-bind (infinitive inf-hint translation tense)
       (org-drill-get-verb-conjugation-info)
     (with-replaced-entry-heading
      (format "%s tense of %s ==> %s\n\n"
diff --git a/spanish.org b/spanish.org
index a88402b2c1..0a87cb9ea4 100755
--- a/spanish.org
+++ b/spanish.org
@@ -175,18 +175,19 @@ direction is chosen at random).
 
 The item has several child items, some of which contain notes about the verb,
 others of which are separate drill items relating to the verb. In this example,
-all the child drill items test verb conjugation, and have the 'conjugate' card
-type. Which tense to test is specified by the =VERB_TENSE= property in each 
item,
-and the information about the verb is retrieved from the parent's
-=VERB_INFINITIVE= and =VERB_TRANSLATION= properties.
+all of the child drill items test verb conjugation, and have the 'conjugate'
+card type. Which tense to test is specified by the =VERB_TENSE= property in
+each item, and the information about the verb is retrieved from the parent's
+=VERB_INFINITIVE=, =VERB_TRANSLATION= and =VERB_INFINITIVE_HINT= properties.
 
 Some of the conjugation items are empty -- this allows the user to past in
-conjugations as they are learned.
+conjugations as they are learned. They will automatically be excluded from
+drill sessions as long as their bodies remain empty.
 
-Following this item is an [[Old Style Verb][example]] of the "spanish_verb" 
card type. This is not
-as sophisticated or useful as the above example, but is intended to demonstrate
-how a function can control which subheadings are visible when an item is
-tested.
+Following this item is an [[Old Style Verb][example]] of the older 
"spanish_verb" card type. This
+is not as sophisticated or useful as the first example, but is intended to
+demonstrate how a function can control which subheadings are visible when an
+item is tested.
 
 
 *** Regular Verb: bailar                                            
:verb:drill:
@@ -195,6 +196,7 @@ tested.
   :VERB_TRANSLATION: "to dance"
   :DRILL_CARD_TYPE: hide1cloze
   :DATE_ADDED: [2011-04-30 Sat]
+  :VERB_INFINITIVE_HINT: "b..."
   :END:
 
 Sp:  [bailar]
@@ -289,6 +291,48 @@ to sing
 Regular verb.
 
 
+** Sentences
+
+
+It is generally a lot harder for language students to translate /to/ the
+foreign language, than to translate /from/ it. This is because when you see a
+sentence in the foreign language, you can often get the sense of the sentence
+by recognising the nouns and verbs; once this is achieved, combining them into
+a grammatically correct sentence in your native tongue is automatic and
+effortless. However, in the other direction, not only do you have to recall the
+correct nouns, verbs and so on, but you also have to put the words in the right
+order and get all the grammar and "in-between words" correct.
+
+Therefore, if you are learning a language you should generally test your
+ability to translate into the language, more often than you test your ability
+in the other direction.
+
+The following is an example of the card type =hide1_firstmore=. This card type
+works like =hide1cloze= but the /first/ clozed text area is guaranteed to be
+hidden 75% of the time.
+
+The second example is of a similar card type, =show1_firstless=. Here only 1
+clozed text area is visible during testing. 75% of the time, the /first/ area
+is guaranteed to be one of the hidden areas.
+
+
+*** Sentence                                                             
:drill:
+    :PROPERTIES:
+    :DRILL_CARD_TYPE: hide1_firstmore
+    :END:
+
+Sp:  [La mujer cuyo perro estamos buscando es mi jefe.]
+En:  [The woman whose dog we’re seeking is my boss.]
+
+*** Adverb                                                               
:drill:
+    :PROPERTIES:
+    :DRILL_CARD_TYPE: show1_firstless
+    :END:
+
+Sp:  [entre]
+En:  [between] or [among]
+
+
 ** Random Numbers
 
 Below is an example of a card that tests the user's ability to translate random



reply via email to

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