Flashcards in LaTeX
Tags: LaTeX, Linux, Languages.
Vocabulary learning is an essential part of learning a new language, and also a tough exercise for your memory. In order to make this task easier, you should devise some techniques for helping you through memorizing new words and concepts. One usual device is vocabulary flashcards, which are two sided cards with a word or concept on the front and the explanation or definition on the back side. In the Figure below there's an example card.
To create such cards in LaTeX, you have to use a documentclass called flashcards, written by Alexander Budge. You can download such class from CTAN. Installation differs slightly between TeX distributions, but should be straightforward. After installing it and reading its documentation, you'll see that its use is also pretty simple. For instance, to create the above card, the tex input file I used was:
\usepackage[ansinew]{inputenc}
\usepackage[english,german,brazilian]{babel}
\cardbackstyle[\small\selectlanguage{english}]{empty}
\cardfrontstyle[\selectlanguage{german}\Large]{headings}
\cardfrontfoot{Deutscher Wortschatz}
\newcommand{\selde}[1]{\selectlanguage{german}\textbf{#1}\selectlanguage{english}}
\newcommand{\selcc}[1]{\selectlanguage{german}\textsf{(#1)}\selectlanguage{english}}
\newcommand{\selbr}[1]{\selectlanguage{brazilian}#1\selectlanguage{english}}
\begin{document}
%END
\begin{flashcard}{verlangen}
1) a. demand, want. \selde{das ist zu viel verlangt} that's asking too much; \selde{von jedem wird pünktlichkeit verlangt} everyone is required or expected to be ponctual; b. require, call for; c. \selcc{berechnen} charge. \selde{sie verlangt 200 DM von ihm}; d. ask for; e. ask to speak to. 2) a. \selde{nach einem Artzt/Priester usw. $\sim$} ask for a doctor/priste etc.; b) \selcc{sich sehnen} \selde{nach jmdm/etw. $\sim$} long for sb/sth. (\selbr{sentir saudades de}).
\end{flashcard}
\end{document}
As you can see in the documentation (or may deduce from the lines pasted above), you simply define the documentclass, the cards type you are going to use, and for each card you simply type:
definition or explanation.
\end{flashcard}
The problem
As simple as it may be, it is a rather tedious process managing to write flashcards directly this way. As the number of cards increases, you'll find yourself having to copy and paste repeatedly syntax commands. You also have to use a somewhat clumsy syntax to type a tilde: instead of simply typing ~, you have to type $\sim$ each time. Also, it's not really practical to number lists by hand (1), 2), 3), as in the example above). Maintaining a list of vocabulary you created over the time is not very practical either as you have to keep them with the hard-coded \begin{flashcard}\end{flashcard} syntax.
The solution
In order to overcome this problem I wrote a Perl script, which, together with a Makefile, automates this process. The script reads the vocabulary stored in a input file, which has a simplified syntax of its own, parses it and using a template for the cards generates a postscript file ready for printing or viewing on screen. Here's an example input file:
verlangen
a. demand, want. {de das ist zu viel verlangt} that's asking too much; {de von jedem wird pünktlichkeit verlangt} everyone is required or expected to be ponctual; b. require, call for; c. {cc berechnen} charge. {de sie verlangt 200 DM von ihm}; d. ask for; e. ask to speak to.
a. {de nach einem Artzt/Priester usw. ~} ask for a doctor/priste etc.; b) {cc sich sehnen} {de nach jmdm/etw. ~} long for sb/sth. ({br sentir saudades de}).
END
START
zumuten
a. {de jmdm. etw. ~} expect or ask sth. of sb.; {de diese Arbeit möchte ich ihm nicht ~} I would not like to ask him to do this work or impose this work on him; {de das ist ihm durchhaus/nicht zuzumuten} it is perfectly reasonable to/one cannot expect or ask that of him; {de sich zu viel ~} take on too much; overdo it. b. {de jmdm. etw. ~} expect sb. to put up with sth.; {de diesen Anblick wollte ich ihm nicht ~} I wanted to spare him this sight.
die Zumutung (-en): a. unreasonable demand, imposition. {de das Essen war eine ~}: the meal was an affront. {de eine ~ für jmdn. sein} be an imposition on sb.
END
Each card is enclosed by the keys START and END. If START is appended with an * (START*), the word is considered during the parsing, otherwise it's ignored. On the first line after the START keyword, comes the word which is to appear on the front of the card. You may force line-breaks with \\. The next lines before the END keyword are then put in the back and numbered from 1) to n), where n is the number of lines of definition. The {xx } environment, provides a way to specify special typographical convention for those blocks, defined in the template file as \selxx. Also ~ is replaced by the script by $\sim$. The template file used for generating the card above was:
\usepackage[english,german,brazilian]{babel}
\cardbackstyle[\small\selectlanguage{english}]{empty}
\cardfrontstyle[\selectlanguage{german}\Large]{headings}
\cardfrontfoot{Deutscher Wortschatz}
\newcommand{\selde}[1]{\selectlanguage{german}\textbf{#1}\selectlanguage{english}}
\newcommand{\selcc}[1]{\selectlanguage{german}\textsf{(#1)}\selectlanguage{english}}
\newcommand{\selbr}[1]{\selectlanguage{brazilian}#1\selectlanguage{english}}
\begin{document}
%END
Everything after %END is ignored by the parser, so that you can test your template with example cards and play with the flashcard class options. Having the input words saved on the file input and the template on the file template.tex, running the script writes to standard output the LaTeX file which can then be processed by LaTeX to generate a printable postscript or pdf file.
Pre-requisites
In order to be able to run the script an properly generate the output file you will need:- A working LaTeX system (which you probably already have since you got this far).
- The flashcards class installed and available on your LaTeX path.
- A working perl interpreter (5.6.x >=)
- GNU Make
- Ghostview to view the postscript output.
- vim - this is optional, just to make the process more practical.
Files you need
- A template.tex file.
- An input file.
- The script itself.
- The Makefile.
Making it work
Make sure you have the pre-requisites. If you're using an *NIX like system you probably just need to install the flashcards package. If you are using other systems, you might have to spend some time installing a Perl distribution and setting up GNU Make to work - but in theory it should work as well.
Make a new directory and download the 4 files indicated above to it. Edit the input and template files as needed and type:
This should parse your input file, generate the TeX output based on the template you provided, LaTeX it to generate a dvi, convert it to postscript and show it to you on Ghostview. If you'd like to use vim, just cd into the directory, and while editing the input file, type:
Which will do the above process inside the text editor, without the need to go back to the console. If everything worked fine, you are going to notice that the output is framed, which is nice to check if your definitions are running out of bounds, which ones need to be corrected etc. When you are done editing a certain input file, you should use another make target for printing, namely:
This will do the same process as above but without frames, making it ready to print.
Printing
The cards I used were the Avery 5371 (or alternatively the Pimaco Cards 7088 - which are exactly the same size and geometry), on a HP DeskJet 850C printer. I found out that the postscript file wouldn't print nicely on my printer; some margins were displaced. So on a error and trial basis I adjusted it passing a parameter to dvips. You should do some tests on the target printer before printing the cards. In order to adjust the output ps, you can use the ps target of the Makefile:
dvips -t letter -O 0,-4mm $(TEXFILE:.tex=.dvi) -o $(TEXFILE:.tex=.ps)
Here the -O 0,-4mm option takes care of adjusting the margin for my particular printer. Your mileage might vary.
Some other notes
It should be straightforward to customize this environment to your particular needs, like vocabulary files for other languages. To work with French vocabulary for example, you'd change some lines in your template, like:
\usepackage[english,french,brazilian]{babel}
...
\cardfrontstyle[\selectlanguage{french}\Large]{headings}
\cardfrontfoot{Vocabulaire de Français}
...
Also the \selxx commands could be changed, adding for example a \selfr one.
Problems
As Rainer Steiger brought it up, there seems to be a problem with the flashcards.cls file on some recent versions of LaTeX. The problem seems related to the geometry package. Basically the .TeX won't compile, complaining about the geometry package, something along the lines of:
See the geometry package documentation for explanation.
Type H <return> for immediate help.
...
l.819 \Gm@process
?
I then remembered that I did indeed had to edit my flashcards.cls in order to make it work, forcing the geometry package to consider the paper letter sized. You can download my modified version here: flashcards.cls. The diff -ru output between the oficial one and mine is:
+++ flashcards.cls.mine 2005-04-19 22:47:05.607376376 -0300
@@ -42,7 +42,7 @@
\NeedsTeXFormat{LaTeX2e}[1996/12/01]
\ProvidesClass{flashcards}[2000/03/14 0.1.1 (ambudge@mit.edu)]
\RequirePackage{ifthen}
-\RequirePackage{geometry}
+\RequirePackage[paper=letterpaper]{geometry}
\LoadClass{article}
\newboolean{flashcards@dvips}\setboolean{flashcards@dvips}{false}
\newboolean{flashcards@grid}\setboolean{flashcards@grid}{false}
@@ -78,7 +78,8 @@
\addtolength{\oddevenshift}{-\evenoffset}
\addtolength{\oddoffset}{-\oddevenshift}
\addtolength{\evenoffset}{\oddevenshift}
-\geometry{\cardpapermode,
+\geometry{compat2,
+ \cardpapermode,
\cardpaper,
top=\topoffset,
left=\oddoffset,
Disclaimer
The code is far from clean, but it's been working quite nicely here for the past months. Among the BUGS I have to address are some inconsistencies on the parser, which chokes on constructions with nested brackets, like {de gro\ss{}spurzen}.
Creation date: 2005-01-20.