summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeon Rische <leon.rische@me.com>2022-09-27 20:23:37 +0200
committerLeon Rische <leon.rische@me.com>2022-09-27 20:23:37 +0200
commit684cf7435f446fd8b90fe0bffae74726b3a75f7d (patch)
tree771bc1b98351e373230d3dbf7d3aaeb261a0e5b1
parent78258557eeb4405416e911324330bbff113a81d0 (diff)
Add documentation files
-rw-r--r--docs/alternative_applications.org16
-rw-r--r--docs/cache.org84
-rw-r--r--docs/card_types.org115
-rw-r--r--docs/components.org66
-rw-r--r--docs/customizing_org-fc.org14
-rw-r--r--docs/dashboard.org15
-rw-r--r--docs/differences_from_other_flashcard_systems.org37
-rw-r--r--docs/extensions.org36
-rw-r--r--docs/hydra.org6
-rw-r--r--docs/incubator.org18
-rw-r--r--docs/index.org66
-rw-r--r--docs/installation.org123
-rw-r--r--docs/introduction.org53
-rw-r--r--docs/marking_headings_as_cards.org47
-rw-r--r--docs/performance.org14
-rw-r--r--docs/repetition_spacing_algorithm.org6
-rw-r--r--docs/review.org102
-rw-r--r--docs/review_contexts.org65
-rw-r--r--docs/review_history.org23
-rw-r--r--docs/suspending_cards.org27
-rw-r--r--docs/use_with_evil-mode.org48
21 files changed, 981 insertions, 0 deletions
diff --git a/docs/alternative_applications.org b/docs/alternative_applications.org
new file mode 100644
index 0000000..82c872e
--- /dev/null
+++ b/docs/alternative_applications.org
@@ -0,0 +1,16 @@
+#+TITLE: Alternative Applications
+#+DATE: [2020-07-17 Fri 00:25]
+#+KEYWORDS: fc
+
+In the most abstract sense, this package deals with
+
+1. Attaching timestamped review information to headlines
+2. Querying all headings where reviews are due
+3. Reviewing due *positions* of headings
+
+While the primary application is learning information using spaced
+repetition, at the end, the API should be flexible enough to implement
+other kinds of repeating tasks where it is necessary to store data in
+addition to the next date.
+
+Some ideas are collected in the [[file:incubator.org][Incubator]].
diff --git a/docs/cache.org b/docs/cache.org
new file mode 100644
index 0000000..234ab9d
--- /dev/null
+++ b/docs/cache.org
@@ -0,0 +1,84 @@
+#+TITLE: Cache
+#+DATE: [2020-07-29 Wed 11:58]
+#+KEYWORDS: fc
+
+* Motivation
+Even with the AWK based indexer, indexing cards before each review
+gets slow if there are a lot of files / cards.
+
+To work around this, the indexer can be run only one time,
+caching the results in a hash table.
+
+Advises are added to `delete-file' and `rename-file'
+remove / update keys from the hash table.
+
+Changes to existing files & new files are detected with a
+~before-save-hook~ on org-mode files.
+
+During a review many files are changed and saved. To keep this as
+fast as possible, instead of re-processing files after each save,
+changed files are collected in `org-fc-cache-queue' and reprocessed in
+bulk the next time the cache is accessed.
+
+Assuming only a small subset of the flashcard files is changed between
+reviews, this is much faster than building the full index ch time.
+
+* Activation
+Caching can be activated/deactivated with ~M-x org-fc-cache-mode~.
+
+To activate this mode when Emacs starts,
+activate it in your configuration:
+
+#+begin_src emacs-lisp
+(org-fc-cache-mode)
+#+end_src
+* Performance
+** Setup
+#+begin_src fish :exports results
+echo (org-files | xargs grep ":fc:" | wc -l) " cards"
+echo (org-files | wc -l) " files"
+org-files | xargs wc -l | tail -n 1 | sed "s/total/lines/g"
+#+end_src
+
+#+RESULTS:
+| 18348 | cards |
+| 2478 | files |
+| 475860 | lines |
+** Benchmarks :noexport:
+#+begin_src emacs-lisp
+ (defun my-org-fc-cache-benchmarks ()
+ (list
+ (list "Dashboard" (benchmark 1 '(org-fc-dashboard 'all)))
+ (list "Index Cards in Subdirectory" (benchmark 1 '(length (org-fc-index '(:paths "~/org/deft/")))))
+ (list "Index Cards with Tag" (benchmark 1 '(length (org-fc-index '(:filter (tag "spanish"))))))))
+#+end_src
+
+#+RESULTS:
+: my-org-fc-cache-benchmarks
+
+** AWK
+#+begin_src emacs-lisp :exports results
+(let ((org-fc-index-function #'org-fc-awk-filter-index))
+ (my-org-fc-cache-benchmarks))
+#+end_src
+
+#+RESULTS:
+| Dashboard | Elapsed time: 3.642393s |
+| Index Cards in Subdirectory | Elapsed time: 0.502262s |
+| Index Cards with Tag | Elapsed time: 3.266725s (0.244461s in 1 GCs) |
+** Cache
+#+begin_src emacs-lisp :exports results
+ (let ((org-fc-index-function #'org-fc-cache-filter-index))
+ (cons
+ (list "Initial Cache Build" (benchmark 1 '(org-fc-cache-build)))
+ (my-org-fc-cache-benchmarks)))
+#+end_src
+
+#+RESULTS:
+| Initial Cache Build | Elapsed time: 2.982310s |
+| Dashboard | Elapsed time: 0.673869s |
+| Index Cards in Subdirectory | Elapsed time: 0.026792s |
+| Index Cards with Tag | Elapsed time: 0.040647s |
+
+Dashboard performance will be improved once a card's review history is
+cached, too.
diff --git a/docs/card_types.org b/docs/card_types.org
new file mode 100644
index 0000000..004bb17
--- /dev/null
+++ b/docs/card_types.org
@@ -0,0 +1,115 @@
+#+TITLE: Card Types
+#+DATE: [2020-08-01 Sat 10:49]
+#+KEYWORDS: fc
+
+* Normal Cards
+During review, the heading is shown with its "Back" subheading
+collapsed, when flipping the card, the back heading is shown,
+then the user is asked to rate the review performance.
+
+Positions: =front=
+* Text-Input Cards
+If the card has a "Back" heading, the first line of its contents is
+considered as the expected answer.
+
+If the card is compact (has no back heading), the first line of its
+main content is used instead.
+
+This allows adding an e.g. explanation to the card.
+
+Answers can be emphasized (e.g. ~foo~). In that case, only the text
+between the emphasis markers is compared to the user input.
+
+On reviewing the card, the users are prompted to enter their answer,
+which is then compared to the expected answer.
+
+The expected answer is overlayed with "<got> (expected: <expected>)",
+coloring correct parts in green and incorrect parts in red.
+
+If the provided answer is shorter than the expected one, a sequence of
+=-= (colored in red) is prepended / appended to it.
+
+This filler character can be customized via ~org-fc-diff-missing-char~.
+
+Positions: =front=
+* Double Cards
+Similar to normal cards, but reviewed both in the "Front -> Back"
+direction and in the "Back -> Front" direction.
+
+Positions: =front=, =back=
+* Cloze Cards
+The cards text contains one or more *holes*. During review, one hole
+is hidden while the text of (some) remaining ones is shown.
+
+Flipping the card reveals the text of the hidden hole,
+using ~org-fc-type-cloze-hole-face~ to highlight it.
+
+Card titles can contain holes, too.
+
+Positions: =0=, =1=, ...
+
+Cloze cards can have a number of sub-types.
+
+** Deletion ~'deletion~
+Only one hole is hidden.
+** Enumerations ~'enumeration~
+All holes *behind* the currently review one are hidden, too.
+
+Useful for memorizing lists where the order of items is important.
+** Single ~'single~
+All holes besides the current one are hidden.
+
+Useful for learning syntax or function names of a programming language
+by using a =src= block in the card and marking parts of the code as
+holes.
+** Context ~'context~
+Holes ~org-fc-type-cloze-context~ (default 1) around the currently
+reviewed one are shown.
+
+Useful for memorizing longer lists where the order of items is important.
+** Hole Syntax
+Deletions can have the following forms
+
+- ~{{text}}~
+- ~{{text}@id}~
+- ~{{text}{hint}}~
+- ~{{text}{hint}@id}~
+
+~text~ should not contain any "}",
+unless it is part of a ~$latex$~ block.
+In this case, ~latex~ should not contain any "$".
+
+Holes *inside* latex blocks are not handled correctly at the moment.
+As a workaround, create multiple smaller latex blocks and wrap each in
+a hole.
+** Image Deletions
+Due to an issue with invisible overlays, images inside cloze-holes are
+not shown correctly during review if the image link directly follows
+the opening ~{{~.
+
+Adding spaces around the image link fixes this problem,
+e.g. ~{{ [[file:my_image.png]] }}~.
+** LaTeX in Cloze Deletions
+LaTeX code in cloze delections can't contain a ~}}~,
+to work around this limitation, insert a space between the braces.
+
+Example: ~\frac{1}{\sqrt{2} }~
+* Compact Cards
+For cards without a "Back" heading, the headline text is considered as
+the front, the main text as the back.
+
+This is useful for cards with a short front text, e.g. when learning
+definitions of words.
+* Defining Own Card Types
+To define a custom card type,
+you need to implement three functions:
+
+- ~(...-init)~ to initialize a heading as a flashcard of this type,
+ setting up the cards properties & review data.
+ Should be marked as ~(interactive)~.
+- ~(...-setup position)~ to setup ~position~ of the card for review
+- ~(...-flip)~ to flip the card
+- ~(...-update)~ to update the review data of the card, e.g. if a new
+ hole is added to a cloze card
+
+All of these are called with ~(point)~ on the cards heading.
diff --git a/docs/components.org b/docs/components.org
new file mode 100644
index 0000000..c43b34f
--- /dev/null
+++ b/docs/components.org
@@ -0,0 +1,66 @@
+#+TITLE: Components
+#+DATE: [2020-08-27 Thu 11:55]
+#+KEYWORDS: fc
+
+Components of org-fc and the most important functions they expose.
+
+* Overview
+#+begin_src plantuml :file images/components.png
+[Index / Query] -* [Dashboard]
+[Index / Query] -* [Review]
+[Index / Query] -- [AWK]
+[Review] -- [Card Types]
+[Review] -- [SM2 Spacing Algorithm]
+[Card Types] -- [Normal]
+[Card Types] -- [Double]
+[Card Types] -- [Text Input]
+[Card Types] -- [Cloze]
+[Text Input] -- [Diff]
+#+end_src
+
+#+RESULTS:
+[[file:images/components.png]]
+
+* ~org-fc-core.el~
+Core functions.
+* ~org-fc-index.el~
+Takes care of indexing and filtering cards.
+
+- ~(org-fc-index context)~ (context is a [[file:review_contexts.org][Review Context]])
+- ~(org-fc-index-positions index)~
+- ~(org-fc-index-shuffled-positions index)~
+
+- ~(org-fc-index-compile-filter filter)~, turns ~filter~ into a lambda
+ function
+
+** ~org-fc-awk.el~
+AWK based indexer.
+* ~org-fc-sm2.el~
+Implementation of the SM2 [[file:repetition_spacing_algorithm.org][Repetition Spacing Algorithm]].
+
+- ~(org-fc-sm2-next-parameters ease box interval rating)~
+ returns a list ~(next-ease next-box next-interval)~
+
+* ~org-fc-review.el~
+Review functionality of org-fc.
+
+- ~(org-fc-review context)~ where ~context~ is a [[file:review_contexts.org][Review Context]]
+- ~(org-fc-demo)~ starts a review of the demo file
+* ~org-fc-diff.el~
+Diff functions for (single-line) strings.
+
+- ~(org-fc-diff got expected)~
+ returns a pair ~(got . expected)~ of colored strings.
+* ~org-fc-dashboard.el~
+Dashboard for org-fc.
+
+- ~(org-fc-dashboard context)~ where ~context~ is a [[file:review_contexts.org][Review Context]]
+* Card Types
+** ~org-fc-type-normal.el~
+Simple front -> back card type.
+** ~org-fc-type-double.el~
+Bidirectional card type (front <-> back).
+** ~org-fc-type-text-input.el~
+Text input cards.
+** ~org-fc-type-cloze.el~
+Card type for cloze deletions.
diff --git a/docs/customizing_org-fc.org b/docs/customizing_org-fc.org
new file mode 100644
index 0000000..9359d78
--- /dev/null
+++ b/docs/customizing_org-fc.org
@@ -0,0 +1,14 @@
+#+TITLE: Customizing Org-Fc
+#+DATE: [2020-08-05 Wed 15:28]
+#+KEYWORDS: fc
+
+For an overview of customization options,
+~M-x customize~ and search for ~org-fc~.
+
+* Hooks
+- ~org-fc-before-setup-hook~
+ Runs before a card is set up for review
+- ~org-fc-after-setup-hook~
+ Runs after a card is set up for review
+- ~org-fc-after-review-hook~
+ Runs when the review ends / is quit
diff --git a/docs/dashboard.org b/docs/dashboard.org
new file mode 100644
index 0000000..9c7ad54
--- /dev/null
+++ b/docs/dashboard.org
@@ -0,0 +1,15 @@
+#+TITLE: Dashboard
+#+DATE: [2020-08-05 Wed 15:29]
+#+KEYWORDS: fc
+
+~M-x org-fc-dashboard~ shows a buffer with statistics for review
+performance and cards / card types.
+
+[[file:images/dashboard.png]]
+
+Review performance statistics are calculated based on
+the [[file:review_history.org][Review History]]. Only cards with a box >=
+~org-fc-stats-review-min-box~ (default: 0) are included.
+
+Setting this to a higher value (e.g. 2) excludes the first few
+"learning" reviews of a card.
diff --git a/docs/differences_from_other_flashcard_systems.org b/docs/differences_from_other_flashcard_systems.org
new file mode 100644
index 0000000..3567d79
--- /dev/null
+++ b/docs/differences_from_other_flashcard_systems.org
@@ -0,0 +1,37 @@
+#+TITLE: Differences from Other Flashcard Systems
+#+DATE: [2020-07-17 Fri 00:42]
+#+KEYWORDS: fc
+
+There are a few other packages implementing a SRS (spaced repetition
+system) based on org-mode.
+
+Below, I've listed a the ones I've found so far that are actively
+maintained and implement a lot of useful functionality.
+
+Thanks to the maintainers and all contributors for their work on these
+projects!
+
+* Other (Open Source) SRS
+- [[https://apps.ankiweb.net/][Anki]]
+- [[https://mnemosyne-proj.org/][Mnemosyne Project]]
+
+The [[file:repetition_spacing_algorithm.org][Repetition Spacing Algorithm]] of org-fc is very similar to the one
+used in Anki.
+
+When working with a large collection of mostly text-based items,
+it's important to have powerful editing possibilities.
+
+org-fc is a SRS built into a (the) most powerful text editor.
+* Org-Mode
+- [[https://gitlab.com/phillord/org-drill/][phillord/org-drill]]
+- [[https://github.com/abo-abo/pamparam][abo-abo/pamparam]]
+
+Among the other org-mode based SRS I've found so far,
+org-fc is unique in that each headline can have multiple "positions"
+that are reviewed independently from each other.
+
+This is very useful for cloze deletions.
+* Memrise :noexport:
+What is does well:
+- presenting cards in different directions / contexts
+- repeating forgotten cards in different ways
diff --git a/docs/extensions.org b/docs/extensions.org
new file mode 100644
index 0000000..30dea9c
--- /dev/null
+++ b/docs/extensions.org
@@ -0,0 +1,36 @@
+#+TITLE: Extensions
+#+DATE: [2020-07-19 Sun 16:06]
+#+KEYWORDS: fc
+
+Org-fc comes with a number of extensions that are not enabled by default.
+
+* ~org-fc-audio~
+Can be enabled with ~(require 'org-fc-audio)~.
+
+Adds audio attachments for cards that are played during review,
+either before or after a card is set up.
+(This distinction is relevant for text-input cards).
+
+Files are played using the ~mpv~ media player.
+
+Commands:
+- ~org-fc-audio-set-before~
+- ~org-fc-audio-set-after~
+* ~org-fc-keymap-hint~
+Can be enabled with ~(require 'org-fc-keymap-hint)~.
+
+Shows a list of available key bindings during the review,
+to recreate the look & feel of the previous hydra-based implementation.
+
+- ~[RET] flip [q] quit [s] suspend-card~
+- ~[a] rate-again [h] rate-hard [g] rate-good [e] rate-easy [s] suspend-card [q] quit~
+* ~org-fc-hydra~
+A hydra for accessing commonly used org-fc commands and for marking
+headlines as flashcards.
+
+It can be loaded and bound to a hotkey like this:
+
+#+begin_src emacs-lisp
+ (require 'org-fc-hydra)
+ (global-set-key (kbd "C-c f") 'org-fc-hydra/body)
+#+end_src
diff --git a/docs/hydra.org b/docs/hydra.org
new file mode 100644
index 0000000..a2d0311
--- /dev/null
+++ b/docs/hydra.org
@@ -0,0 +1,6 @@
+#+TITLE: Hydra
+#+DATE: [2020-08-05 Wed 15:31]
+#+KEYWORDS: fc
+
+The org-fc hydra provides a quick way of interacting with the
+flashcard system.
diff --git a/docs/incubator.org b/docs/incubator.org
new file mode 100644
index 0000000..bd80791
--- /dev/null
+++ b/docs/incubator.org
@@ -0,0 +1,18 @@
+#+SETUPFILE: ~/org/setup.org
+#+TITLE: Incubator
+#+DATE: [2020-07-17 Fri 00:33]
+#+KEYWORDS: fc
+
+* Presentations using org-mode
+- Cloze-like cards for revealing points of a list
+* Workout Tracker / Timer
+One example would be storing one exercise per heading, using the
+positions to store one or more sets and logging the number of
+repetitions done on each "review".
+
+- TTS for instructions
+- Exercise / Pause Timer
+* Mood Tracking
+- Store History in table instead of CSV file
+* Sharing Support, Merging of Changed Cards
+1. strip review data, creation date
diff --git a/docs/index.org b/docs/index.org
new file mode 100644
index 0000000..0e75ffa
--- /dev/null
+++ b/docs/index.org
@@ -0,0 +1,66 @@
+#+TITLE: Org Flashcards
+#+DATE: [2020-07-17 Fri 00:16]
+#+KEYWORDS: fc
+
+- [[https://git.sr.ht/~l3kn/org-fc][Git]]
+- [[https://lists.sr.ht/~l3kn/org-fc][Mailing List]]
+- [[https://todo.sr.ht/~l3kn/org-fc][Issue Tracker]]
+
+[[file:images/review.png]]
+
+* Introduction
+Org-fc is a spaced-repetition system for Emacs' org-mode.
+
+It allows you to mark headlines in a file as "flashcards", turning
+pieces of knowledge you want to learn into a question-answer test.
+
+These cards are reviewed at regular interval. After each review, a
+[[file:repetition_spacing_algorithm.org][Repetition Spacing Algorithm]] is used to calculate the next interval
+based on how well you remembered the contents of the card.
+* Getting Started
+Start by [[file:installation.org][installing org-fc]] using the package manager of your choice.
+
+A file demonstrating all [[file:card_types.org][Card Types]] is included. ~M-x org-fc-demo~
+starts a review of this file.
+
+To create your own flashcards, create a heading in an org-mode file
+and [[file:marking_headings_as_cards.org][mark it as a flashcard]], using either one of the
+~org-fc-type-...-init~ commands (e.g. ~org-fc-type-normal-init~)
+or the [[file:hydra.org][org-fc Hydra]] (e.g. =C-c f= to open it, =t= to initialize a
+new card, =n= to select the normal card type).
+
+Once you've created a bunch of cards, you can start a [[file:review.org][Review Session]]
+with ~M-x org-fc-review~ (=C-c f r= in the hydra).
+
+~M-x org-fc-dashboard~ (=C-c f m= in the hydra) opens a [[file:dashboard.org][Dashboard]]
+with statistics on the flashcards in the system.
+
+Before reviews and when opening the dashboard, you're asked to select
+a [[file:review_contexts.org][Review Context]]. These can be used to group cards to review them
+separately from each other, e.g. when learning multiple languages.
+
+Note 1: The [[file:hydra.org][Hydra]] is not enabled by default, add ~(require
+'org-fc-hydra)~ to your configuration to load it.
+
+Note 2: Make sure to check out [[file:use_with_evil-mode.org][Use with Evil-Mode]] if you're using
+evil-mode.
+
+Note 3: Before starting the review, make sure to add the directory of
+your org files to ~org-fc-directories~, e.g. via ~(setq
+org-fc-directories '("/my-org-files/"))~
+* Design Goals / Choices
+- [[file:differences_from_other_flashcard_systems.org][Differences from Other Flashcard Systems]]
+- Good [[file:performance.org][Performance]]
+ - =awk= is used for quickly finding cards due for review,
+ instead of relying on the slow org-element parser
+- Support for multiple *positions* in a card / heading
+- All relevant data kept in org files for easy version control
+- Review directly on the source org file for easy editing of cards
+ during review
+* Advanced Topics
+- [[file:components.org][Components]]
+- [[file:alternative_applications.org][Alternative Applications]]
+- [[file:extensions.org][Extensions]]
+- [[file:customizing_org-fc.org][Customizing Org-Fc]]
+* License
+Copyright © Leon Rische and contributors. Distributed under the GNU General Public License, Version 3
diff --git a/docs/installation.org b/docs/installation.org
new file mode 100644
index 0000000..59ba39b
--- /dev/null
+++ b/docs/installation.org
@@ -0,0 +1,123 @@
+#+TITLE: Installation
+#+DATE: [2020-08-05 Wed 15:31]
+#+KEYWORDS: fc
+
+Before using this package, ~org-fc-directories~ should be set to the
+directory to search for org files containing flashcards.
+
+The file used to store the review history can be customized with
+~org-fc-review-history-file~ and defaults to ~/path/to/config/org-fc-reviews.tsv~.
+
+This package is not (yet) available on MELPA / ELPA,
+to install it, clone the repository (e.g. to ~src/org-fc/~)
+and follow the setup instructions.
+
+* Dependencies
+Org-fc has been tested with org-mode version 9.3.6 and gawk version
+5.1.0. You can check your versions with ~M-x org-version~
+and ~gawk -V~.
+
+- The =gawk= extension of =awk= for extracting review data from =.org= files
+- =find= for finding all org files in the ~org-fc-directories~
+- =xargs= for processing files in parallel
+** Linux / UNIX
+=find= and =xargs= should be included in most distributions, =gawk=
+can be installed from source or using your package manager of choice.
+
+Examples:
+- =pacman -S gawk= (Arch Linux)
+- =apt-get install gawk= (Ubuntu, Debian, ...)
+- =yum install gawk= (CentOS)
+
+For more information, see [[https://www.gnu.org/software/gawk/manual/html_node/Installation.html][gawk manual - Installation]].
+** MacOS
+On MacOS all dependencies can be installed using [[https://www.macports.org/][macports]] or [[https://brew.sh/][homebrew]].
+=find= and =xargs= are part of the =findutils= package.
+
+- =port install gawk findutils=
+- =brew install gawk findutils=
+
+You might have to adjust your =$PATH= to make sure Emacs can find all
+relevant binaries.
+
+#+BEGIN_SRC
+ export PATH="/opt/local/libexec/gnubin:/opt/local/bin:$PATH"
+#+END_SRC
+
+For more information, refer to the documentation of macports /
+homebrew.
+* Manual Installation
+#+begin_src bash
+ cd ~/src/
+ git clone https://git.sr.ht/~l3kn/org-fc
+#+end_src
+
+#+BEGIN_SRC emacs-lisp
+ (add-to-list 'load-path "~/src/org-fc/")
+
+ (require 'org-fc)
+ (require 'org-fc-hydra)
+
+ (setq org-fc-directories '("~/org/"))
+#+END_SRC
+* Setup with [[https://github.com/jwiegley/use-package/][use-package]]
+Assuming you've manually cloned the repository.
+
+#+BEGIN_SRC emacs-lisp :eval no-export
+ (use-package hydra)
+ (use-package org-fc
+ :load-path "~/src/org-fc"
+ :custom (org-fc-directories '("~/org/"))
+ :config
+ (require 'org-fc-hydra))
+#+END_SRC
+
+Or, using [[https://github.com/raxod502/straight.el/][straight.el]]:
+
+#+BEGIN_SRC emacs-lisp :eval no-export
+ (use-package hydra)
+ (use-package org-fc
+ :straight
+ (org-fc
+ :type git :repo "https://git.sr.ht/~l3kn/org-fc"
+ :files (:defaults "awk" "demo.org"))
+ :custom
+ (org-fc-directories '("~/org/"))
+ :config
+ (require 'org-fc-hydra))
+#+END_SRC
+
+Note that in this case, you don't have to clone the repository.
+* Setup with [[https://github.com/raxod502/straight.el/][straight.el]]
+#+BEGIN_SRC emacs-lisp :eval no-export
+ (straight-use-package 'hydra)
+ (straight-use-package
+ '(org-fc
+ :type git :repo "https://git.sr.ht/~l3kn/org-fc"
+ :files (:defaults "awk" "demo.org")
+ :custom (org-fc-directories '("~/org/"))
+ :config
+ (require 'org-fc-hydra)))
+#+END_SRC
+
+* Setup with [[https://github.com/syl20bnr/spacemacs/][spacemacs]]
+You don't need to manually clone the repository,
+just put this in your =.spacemacs=:
+
+#+BEGIN_SRC emacs-lisp :eval no-export
+ ;; ...
+ dotspacemacs-additional-packages
+ '((org-fc
+ :location (recipe :fetcher git
+ :url "https://git.sr.ht/~l3kn/org-fc"
+ :files (:defaults "awk" "demo.org"))))
+ ;; ...
+ (defun dotspacemacs/user-config ()
+ ;; ...
+ ;; Org-fc
+ (use-package hydra)
+ (require 'org-fc-hydra)
+ (setq org-fc-directories '("~/org/"))
+ ;; ...
+ )
+#+END_SRC
diff --git a/docs/introduction.org b/docs/introduction.org
new file mode 100644
index 0000000..c9dc4d9
--- /dev/null
+++ b/docs/introduction.org
@@ -0,0 +1,53 @@
+#+TITLE: Introduction
+#+DATE: [2020-07-17 Fri 01:07]
+#+FILETAGS: :fc-demo:
+#+KEYWORDS: fc
+
+* Welcome to org-fc :suspended:fc:
+:PROPERTIES:
+:FC_CREATED: 2020-07-16T23:14:28Z
+:FC_TYPE: normal
+:ID: 78877a24-22f3-4996-8fc1-544204cda0b0
+:END:
+:REVIEW_DATA:
+| position | ease | box | interval | due |
+|----------+------+-----+----------+----------------------|
+| front | 2.5 | 0 | 0 | 2020-07-16T23:14:28Z |
+:END:
+This is an interactive introduction into org-fc,
+using org-fc.
+
+You're currently (re)viewing the front of a flashcard.
+To "flip" it, revealing the contents of its "Back" heading,
+press the enter key.
+
+You can quit the review at any time by pressing "q".
+** Back
+This is the back side of the flashcard.
+
+You can now rate how well you remembered the information on the back
+side of the card.
+* The "normal" Card Type :suspended:fc:
+:PROPERTIES:
+:FC_CREATED: 2020-07-16T23:20:50Z
+:FC_TYPE: normal
+:ID: 8f01a1c9-c842-48b8-9952-ca1c38875703
+:END:
+:REVIEW_DATA:
+| position | ease | box | interval | due |
+|----------+------+-----+----------+----------------------|
+| front | 2.5 | 0 | 0 | 2020-07-16T23:20:50Z |
+:END:
+Let's try that again!
+
+What are the two sides of a "normal" flashcard
+like the one you have just seen?
+** Back
+- front (i.e. question)
+- back (i.e. answer)
+* WAITING Use inline-evaluation for key bindings :noexport:
+:PROPERTIES:
+:ID: 5f3f2a87-d7b9-409c-af97-691643f07b4d
+:END:
+- Requires inline-evaluation / insertion of lisp code
+- Similar to org (export) macros
diff --git a/docs/marking_headings_as_cards.org b/docs/marking_headings_as_cards.org
new file mode 100644
index 0000000..c6ba5d2
--- /dev/null
+++ b/docs/marking_headings_as_cards.org
@@ -0,0 +1,47 @@
+#+TITLE: Marking Headings As Cards
+#+DATE: [2020-08-07 Fri 14:34]
+#+KEYWORDS: fc
+
+A *card* is an org-mode headline with a =:fc:= tag attached to it.
+Each card can have multiple *positions* reviewed independently from
+each other, e.g. one for each hole of a cloze card.
+
+Review data (ease, interval in days, box, due date) is stored in a table
+in a drawer inside the card.
+
+#+BEGIN_EXAMPLE
+ :REVIEW_DATA:
+ | position | ease | box | interval | due |
+ |----------+------+-----+----------+------------------------|
+ | 2 | 2.65 | 6 | 107.13 | 2020-04-07T01:01:00 |
+ | 1 | 2.65 | 6 | 128.19 | 2020-04-29T06:44:00 |
+ | 0 | 2.95 | 6 | 131.57 | 2020-04-30T18:03:00 |
+ :END:
+#+END_EXAMPLE
+
+The [[file:review_history.org][Review History]] is stored in a TSV file to avoid cluttering the org
+files.
+
+Each card needs at least two properties, an *unique* ~:ID:~ and a
+~:FC_TYPE:~. In addition to that, the date a card was created
+(i.e. the headline was marked as a flashcard) is stored to allow
+creating statistics for how many cards were created in the last day /
+week / month.
+
+#+BEGIN_EXAMPLE
+ :PROPERTIES:
+ :ID: 4ffe66a7-7b5c-4811-bd3e-02b5c0862f55
+ :FC_TYPE: normal
+ :FC_CREATED: 2019-10-11T14:08:32
+ :END:
+#+END_EXAMPLE
+
+Card types (should) implement a ~org-fc-type-...-init~ command that
+initializes these properties and sets up the review data drawer
+
+All timestamps created and used by org-flashcards use ISO8601 format
+with second precision and without a timezone (timezone UTC0).
+
+This prevents flashcard due dates from showing up in the org-agenda
+and allows filtering for due cards by string-comparing a timestamp
+with one of the current time.
diff --git a/docs/performance.org b/docs/performance.org
new file mode 100644
index 0000000..3d2df8a
--- /dev/null
+++ b/docs/performance.org
@@ -0,0 +1,14 @@
+#+TITLE: Performance
+#+DATE: [2020-07-19 Sun 16:01]
+#+KEYWORDS: fc
+
+All user-facing commands (especially during review) should be as fast
+as possible (<300ms).
+
+Using the =awk= indexer, searching 2500 org files (~200k lines in
+total) for due flashcards takes around ~500ms on my laptop (Thinkpad
+L470, SSD).
+
+Using a lisp indexer based on ~org-map-entries~,
+searching a single 6500 line file with 333 flashcards takes ~1000ms,
+indexing the same file with =awk= takes around ~50ms.
diff --git a/docs/repetition_spacing_algorithm.org b/docs/repetition_spacing_algorithm.org
new file mode 100644
index 0000000..aaa4356
--- /dev/null
+++ b/docs/repetition_spacing_algorithm.org
@@ -0,0 +1,6 @@
+#+TITLE: Repetition Spacing Algorithm
+#+DATE: [2020-07-17 Fri 00:46]
+#+KEYWORDS: fc
+
+This package uses a modified version of the [[https://www.supermemo.com/en/archives1990-2015/english/ol/sm2][SuperMemo - SM2 Algorithm]]
+algorithm, based on the one used by [[https://apps.ankiweb.net/docs/manual.html#what-algorithm][Anki]].
diff --git a/docs/review.org b/docs/review.org
new file mode 100644
index 0000000..74a39d3
--- /dev/null
+++ b/docs/review.org
@@ -0,0 +1,102 @@
+#+TITLE: Review
+#+DATE: [2020-08-05 Wed 15:29]
+#+KEYWORDS: fc
+
+A review session can be started with ~M-x org-fc-review~. Due cards
+are reviewed in random order.
+
+If a card was rated "again", it will be reviewed again at the end of
+the current review session. This can be disabled by setting
+~org-fc-append-failed-cards~ to ~nil~.
+
+[[file:review_contexts.org][Review Contexts]] can be used to only review cards of a set tag or type,
+e.g. when using org-fc to learn different foreign languages where
+mixing them in one review session would lead to confusion.
+
+Each time a card is rated, an entry is added to the [[file:review_histord.org][Review History]].
+
+Cards can be excluded from review without deleting them
+by [[file:suspending_cards.org][suspending them]].
+
+* Review Process
+1. Open file of card
+2. Narrow to heading
+3. Set up card for review
+4. Activate ~org-fc-flip-mode~
+5. Flip the card (user)
+6. Switch to ~org-fc-rate-mode~
+7. Rate the card (user)
+8. Repeat process with next due card
+
+#+begin_src plantuml :file images/review_loop.png
+"Review next Card" -> if "Another card due?" then
+ -->[true] "Open file of card\nNarrow\nSet up\nflip-mode"
+ --> if "Action" then
+ -->[flip] "Flip Card\nrate-mode"
+ --> if "Action" then
+ -->[again] "Append Card"
+ --> "Update Review Data"
+ else
+ -->[hard / good / easy] "Update Review Data"
+ --> "Review next Card"
+ else
+ -->[suspend] "Suspend Card"
+ --> "Review next Card"
+ else
+ ->[edit] "Edit Card"
+ --> "Open file of card\nNarrow\nSet up\nflip-mode"
+ else
+ -->[quit] "Quit Review"
+ endif
+ else
+ -->[quit] "Quit Review"
+ endif
+else
+ -->[false] "Quit Review"
+endif
+#+end_src
+
+#+RESULTS:
+[[file:images/review_loop.png]]
+
+#+begin_src plantuml :file images/review_sequence.png
+actor User
+collections Card
+database Index
+
+User -> Index: Start Review
+Index -> Card: Jump to next due card
+Card -> Card: Narrow to card heading
+Card -> Card: Set up card
+User -> Card: Flip card
+User -> Card: Rate card
+Card -> Index: Update review data
+Index -> Card: Jump to next due card
+... Repeat ...
+#+end_src
+
+By default failed cards (rated again) are appended to the current
+review session. This can be disabled with ~(setq
+org-fc-append-failed-cards nil)~.
+
+#+RESULTS:
+[[file:images/review_sequence.png]]
+
+* Flip Mode
+| Key | Binding |
+|-----+--------------------------|
+| RET | flip card |
+| n | flip card |
+| s | suspend card |
+| p | pause review for editing |
+| q | quit review |
+* Rate Mode
+| Key | Binding |
+|-----+--------------------------|
+| a | rate again |
+| h | rate hard |
+| g | rate good |
+| e | rate easy |
+| s | suspend card |
+| p | pause review for editing |
+| q | quit review |
diff --git a/docs/review_contexts.org b/docs/review_contexts.org
new file mode 100644
index 0000000..9b737fb
--- /dev/null
+++ b/docs/review_contexts.org
@@ -0,0 +1,65 @@
+#+TITLE: Review Contexts
+#+DATE: [2020-08-01 Sat 10:41]
+#+KEYWORDS: fc
+
+By default, two contexts are defined:
+
+- all :: all cards in ~org-fc-directories~
+- buffer :: all cards in the current buffer
+
+New contexts can be defined by adding them to the alist
+~org-fc-custom-contexts~.
+
+Contexts have the form ~(:paths paths :filter filter)~.
+
+- ~:paths~ (optional)
+ either a list of paths, a single path
+ or ~'buffer~ for the current buffer.
+ Paths don't have to be included in the ~org-fc-directories~.
+ Defaults to ~org-fc-directories~.
+- ~:filter~ (optional), a card filter defaulting to a filter that
+ matches all cards.
+
+Filters can be combinations of the following expressions:
+
+- ~(and ex1 ex2 ...)~
+- ~(or ex1 ex2 ...)~
+- ~(not ex)~
+- ~(tag "tag")~
+- ~(type card-type) or (type "card-type")~
+
+* Examples
+All double cards with tag "math":
+#+begin_src emacs-lisp
+ (add-to-list 'org-fc-custom-contexts
+ '(double-math-cards . (:filter (and (type double) (tag "math")))))
+#+end_src
+
+All cards in that don't have one of the tags "foo" and "bar":
+#+begin_src emacs-lisp
+ (add-to-list 'org-fc-custom-contexts
+ '(no-foo-bar-cards . (:filter (not (or (tag "foo") (tag "bar"))))))
+#+end_src
+
+All cards in =~/combinatorics/= or =~/number_theory.org=:
+#+begin_src emacs-lisp
+ (add-to-list 'org-fc-custom-contexts
+ '(math-cards . (:paths ("~/combinatorics/" "~/number_theory.org"))))
+#+end_src
+
+All cards in =~/combinatorics/= with tag "theorem":
+#+begin_src emacs-lisp
+ (add-to-list 'org-fc-custom-contexts
+ '(combinatorics-theorems .
+ (:paths "~/combinatorics/" :filter (tag "theorem"))))
+#+end_src
+
+All double cards in the current buffer:
+#+begin_src emacs-lisp
+ (add-to-list 'org-fc-custom-contexts
+ '(current-double .
+ (:paths buffer :filter (type double))))
+#+end_src
+* Note
+Because parsing of tags is done in AWK, tag filters don't work for
+tags defined in the =#+FILETAGS:= of a =#+SETUP_FILE:=.
diff --git a/docs/review_history.org b/docs/review_history.org
new file mode 100644
index 0000000..84d7861
--- /dev/null
+++ b/docs/review_history.org
@@ -0,0 +1,23 @@
+#+TITLE: Review History
+#+DATE: [2020-08-01 Sat 10:47]
+#+KEYWORDS: fc
+
+The review history is stored in a tsv file, to avoid cluttering org
+files. This makes it easy to calculate review statistics.
+
+Columns:
+1. Date in ISO8601 format, second precision
+2. Filename
+3. Card ID
+4. Position
+5. Ease (before review)
+6. Box (before review)
+7. Interval (before review)
+8. Rating
+9. Seconds spent reviewing the card
+10. [[file:repetition_spacing_algorithm.org][Repetition Spacing Algorithm]] used
+
+More advanced review algorithms might need to use the review history
+of a card. In this case, the card ID + position should be used to look
+up the review history, as the filename can change when moving cards
+from file to file.
diff --git a/docs/suspending_cards.org b/docs/suspending_cards.org
new file mode 100644
index 0000000..0fd4d82
--- /dev/null
+++ b/docs/suspending_cards.org
@@ -0,0 +1,27 @@
+#+TITLE: Suspending Cards
+#+DATE: [2020-08-01 Sat 10:55]
+#+KEYWORDS: fc
+
+Cards can be suspended (excluded from review) by adding a =suspended=
+tag, either by hand or using the ~org-fc-suspend-card~ command.
+
+The =suspended= tag is inherited, so all cards in a subtree can be
+suspended by adding the tag to the parent heading, and all cards in a
+file can be suspended by adding ~#+FILETAGS: suspended~ at the start.
+
+Cards can be unsuspended using the ~org-fc-unsuspend-card~ command
+or by manually removing the =suspended= tag.
+
+It might be preferable to suspend multiple cards by adding the
+=suspended= tag to each one, so they remain suspended
+when moved to another headline or file.
+
+In this case, you can use the following commands:
+
+- ~org-fc-suspend-tree~, ~org-fc-unsuspend-tree~ for suspending all
+ cards in a subtree
+- ~org-fc-suspend-buffer~, ~org-fc-unsuspend-buffer~ for suspending all
+ cards in the current buffer
+
+Note that these commands don't affect filetags or tags of parent
+headlines.
diff --git a/docs/use_with_evil-mode.org b/docs/use_with_evil-mode.org
new file mode 100644
index 0000000..154eb23
--- /dev/null
+++ b/docs/use_with_evil-mode.org
@@ -0,0 +1,48 @@
+#+TITLE: Use with Evil-Mode
+#+DATE: [2020-07-19 Sun 16:03]
+#+KEYWORDS: fc
+
+The key bindings used by the review modes of org-fc conflict with
+some of the bindings used by evil mode.
+
+As a workaround, you can add minor mode keymaps for
+each of the evil-mode states you're using org-fc with.
+
+#+begin_src emacs-lisp
+(evil-define-minor-mode-key '(normal insert emacs) 'org-fc-review-flip-mode
+ (kbd "RET") 'org-fc-review-flip
+ (kbd "n") 'org-fc-review-flip
+ (kbd "s") 'org-fc-review-suspend-card
+ (kbd "q") 'org-fc-review-quit)
+
+(evil-define-minor-mode-key '(normal insert emacs) 'org-fc-review-rate-mode
+ (kbd "a") 'org-fc-review-rate-again
+ (kbd "h") 'org-fc-review-rate-hard
+ (kbd "g") 'org-fc-review-rate-good
+ (kbd "e") 'org-fc-review-rate-easy
+ (kbd "s") 'org-fc-review-suspend-card
+ (kbd "q") 'org-fc-review-quit)
+#+end_src
+
+* Using general.el for Keybindings
+#+begin_src emacs-lisp
+ (general-define-key
+ :definer 'minor-mode
+ :states 'normal
+ :keymaps 'org-fc-review-flip-mode
+ "RET" 'org-fc-review-flip
+ "n" 'org-fc-review-flip
+ "s" 'org-fc-review-suspend-card
+ "q" 'org-fc-review-quit)
+
+ (general-define-key
+ :definer 'minor-mode
+ :states 'normal
+ :keymaps 'org-fc-review-rate-mode
+ "a" 'org-fc-review-rate-again
+ "h" 'org-fc-review-rate-hard
+ "g" 'org-fc-review-rate-good
+ "e" 'org-fc-review-rate-easy
+ "s" 'org-fc-review-suspend-card
+ "q" 'org-fc-review-quit)
+#+end_src