Intro
Pamparam is a new spaced repetition (SR) memory cards implementation for Emacs.
Spaced repetition is an algorithm for learning and repeating cards. Cards for which you get high scores get scheduled for repetition much further into the future than those with low scores. This means you spend less time repeating things that are easy for you to remember and more time on things which are hard for you to remember.
Quickstart
git clone https://github.com/abo-abo/pamparam
- Open
pamparam/doc/sets/capitals/capitals.org
and callpamparam-sync
.You get a message like
35 new cards, 0 updated, 35 total
and the filepampile.org
is opened. - Call
pamparam-drill
.You get two buffers. One buffer, named e.g.
pam-2017-04-23.org
is your schedule file. It holds 10 cards that you should do today. The other buffer is a card asking you the capital of e.g.Estonia
. - Enter
Tallinn.
(the dot at the end starts the card validation)Since the answer is correct, you get a score of 5 (best one). Alternatively, if you reveal the answer with
S-TAB
and enterTallinn.
, you will get only a score of 3. Finally, if you enter a wrong answer, you get a score of 0. - Theoretically, you can stop here with 1/10 cards done. Resume at
any later stage with
pamparam-drill
. Or pressn
(callspamparam-drill
) to select the next card. Any cards scheduled today but not finished will carry over to tomorrow.
Assuming you finished all 10 cards, what’s next?
- (optional) call
pamparam-commit
to commit your progress.It’s not really required, but it’s neat to track everything, and it’s a nice restore point if you ever mess up your repo.
- if you feel like doing more cards, call
pamparam-pull
.I don’t recommend doing more than 50 cards in a day, because you’ll be spending a lot of time on repetition in the future.
- come back tomorrow for a new set of cards to repeat and learn.
How this works
Terminology
After pamparam-sync
and pamparam-drill
, you get the following tree:
. ├── capitals.org └── capitals.pam ├── cards │  ├── 00 │  │  └── 00247297c394dd443dc97067830c35f4-a606fe014370d8c520a07f30df46ef10.org │  ├── 01 │  │  └── 01a151debf2bfee8906f43f4342eb10b-654cd76590cebe0ba37e8d4cce8a96ee.org │ ... (more cards) ... ├── pam-2017-04-23.org ├── pam-2017-04-24.org └── pampile.org
With this example, let’s get the terminology out of the way:
- Master file
- e.g.
capitals.org
,This is an Org file that has a heading tagged with
:cards:
that contains the definition of all your cards. - Card file
- e.g.
capitals.pam/cards/00/00247297c394dd443dc97067830c35f4-a606fe014370d8c520a07f30df46ef10.org
This is an Org file that encapsulates a single card. Besides the front (the question) and the body (the answer), it also contains the metadata. The metadata contains: dates and scores of previous learning sessions with this card and the card’s accumulated ease factor.
- Schedule file
- e.g.
capitals.pam/pam-2017-04-23.org
This is an Org file that stores the schedule for a particular day as
TODO
items with links to card files. Each item’s state starts atTODO
and ends atDONE
which you finish the corresponding card. An intermediate stateREVIEW
happens if you get a score lower than 5 for the first time. When doing the card for the second time,REVIEW
becomesDONE
with a score of 3 or more. - Pile file
capitals.pam/pampile.org
This is your cards pile. Very similar to a schedule file, it holds all cards that are not yet scheduled. There are two ways to interact with your pile: add to it by calling
pamparam-sync
from the master file or remove from it by callingpamparam-pull
.- Repo
capitals.pam
A Git repository to store all your cards files, schedules, and the pile. Note that the master file isn’t here. This is intentional, since any of your existing Org can become a master file simply by adding a
:cards:
tag to one of the outlines. Seepamparam-alist
for a way to connect a master file to a repo that’s not in the same directory.
Master file example
A master file is an Org-mode file with things you want to learn.
One simple example is provided in capitals.org.
Here’s another, slightly more elaborate, example, which I use for learning Dutch:
* Cards :cards:
** comic story
het stripverhal
*** The Adventures of Tintin is a world famous Belgian comic strip.
De Avonturen van Kuifje is een wereldbekend Belgisch stripverhaal.
** singer
de zanger
de zangeres
*** The singer is only known in Belgium.
De zangeres is alleen in België bekend.
The format of the master file is fairly straightforward:
- There needs to be one or more card sources - first level outlines
marked with the
:cards:
tag. A separate card file will be created for every second or third level child of each card source. In the example above, four cards will be created. - For each second or third level outline, the heading name is the
question and the heading body is the answer. I usually put e.g. a
noun or a verb into the second level, and a more elaborate example
of using that noun or a verb into the child third level. I also
like to organize the words by generation rules and thematically, so
that e.g.
honest
will be close tomodest
and very close tohonesty
.The only hard and enforced requirement is that all heading names must be unique.
- If a word has many correct possibilities (like
de zanger
andde zangeres
both meansinger
), I put each on its own line. This allows to enter either synonym during validation.
The master file is a great summary of the info that you have available. It’s easy to search and organize.
One more option is to put all cards as level one headings. In that case, instead of
tagging them with :cards:
, you can add to the top of the file:
#+PROPERTY: pamparam t
Card file example
A card file looks like this:
* m
#+STARTUP: content
** scores
| <2017-04-23> | 3 | |
** stats
(setq ease-factor 2.360000)
(setq intervals '(1))
* Slovenia
Ljubljana
The first heading holds all the metadata, like:
- all times and scores when you did a card
- your wrong answers, if any
- an estimate of the card’s ease
The second heading’s name is the card’s front, the question. The second heading’s body is the anwer, it starts out hidden.
Card scoring
score | meaning |
---|---|
5 | perfect answer, body hidden |
4 | wrong answer, pamparam-card-redo was called, followed by a perfect answer |
3 | perfect answer, body revealed |
0 | wrong answer |
On the first try, you can get either a 5 or a 3 or a 0. Unless you get
a 5, you have to REVIEW
the card today.
You can use pamparam-card-redo
if you make a mechanical typo and get a 0,
even though you knew the card. If you manage to correct the typo, you
get a 4. You can make use of C-y
to yank your previous answer.
In the REVIEW
stage, entering the answer with body revealed is
acceptable to move it to DONE
. Still, you might want to try to keep
the body hidden.
Commands and key bindings
Certain commands are applicable only in certain types of files. There
are 3 types of files, all of which use org-mode
: master, card and
schedule.
Card file
Global bindings:
. | pamparam-card-validate-maybe |
Local bindings (only active if your point is at a heading start), in order of importance:
n | pamparam-drill |
q | bury-buffer |
R | pamparam-card-redo |
D | pamparam-card-delete |
Master file
pamparam-sync |
Anywhere in the repo
pamparam-drill |
pamparam-pull |
pamparam-commit |
Customization
While it’s possible to have multiple repos, currently I have only a
single one. In my case, it’s not convenient to keep the repo dutch.pam
in the same directory as the master file dutch.org
. So I use this
setting:
(setq pamparam-alist
'(("/home/oleh/Dropbox/org/wiki/dutch.org"
. "/home/oleh/Dropbox/source/site-lisp/git/dutch.pam")))
pamparam-drill
doesn’t know where your repos are located. It can only
determine if the current buffer’s file belongs to a repo or not. In
case it does, the current repo is used. Otherwise, the default repo is
used which is pointed to by pamparam-path
.
By default, pamparam-path
points to the repo of the provided example master
file. Here’s my custom setting:
(setq pamparam-path "/home/oleh/Dropbox/source/site-lisp/git/dutch.pam")
Finally, you can have all key bindings in one place with a hydra:
(global-set-key (kbd "C-c m") 'hydra-pam/body)