summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md112
-rw-r--r--doc/gnosis.info350
-rw-r--r--doc/gnosis.org235
-rw-r--r--doc/gnosis.texi324
-rw-r--r--gnosis-algorithm.el51
-rw-r--r--gnosis.el234
6 files changed, 1063 insertions, 243 deletions
diff --git a/README.md b/README.md
index cb2cb5e..fdff0a1 100644
--- a/README.md
+++ b/README.md
@@ -3,114 +3,8 @@
## About
-Gnosis (γνῶσις), pronounced "noh-sis", meaning knowledge in Greek, is
+Gnosis (γνῶσις), pronounced "noh-sis", *meaning knowledge in Greek*, is
a [Spaced Repetition](https://en.wikipedia.org/wiki/Spaced_repetition)
-package for GNU Emacs.
+System (SRS) for note taking and self testing.
-### Differences with other SRS
-Gnosis does not implement flashcard type review sessions where the
-user rates his own answer on an arbitrary scale. Instead implements
-"note" types that require user input. Some of these note types, like
-the `MCQ` *multiple choice question*, even allow for simulating
-real-life exams.
-
-Unlike other SRS implementations for GNU Emacs that rely on
-`org-mode`, which I've found not an ideal option for a database
-replacement. Instead utilizes an
-[sqlite](https://www.sqlite.org/index.html) database, thanks to
-[emacsql](https://github.com/magit/emacsql), enabling efficient data
-management and manipulation.
-
-## Installation
-### Straight.el
-``` emacs-lisp
-(straight-use-package
- '(gnosis :type git
- :host nil
- :repo "https://git.thanosapollo.org/gnosis"))
-```
-
-### Manual
-``` shell
-$ git clone https://git.thanosapollo.org/gnosis
-```
-
-*Add this to your emacs configuration:*
-
-``` emacs-lisp
- (add-to-list 'load-path "/path/to/gnosis")
- (load-file "~/path/to/gnosis.el")
- (require 'gnosis)
-```
-
-
-## Adding notes
-
-Creating notes for gnosis can be done with a simple
-`M-x gnosis-add-note`
-
-
-Everything is done through the mini-buffer. My personal workflow takes
-advantage of that by not really leaving `gnosis-add-note` prompt until
-I finish studying a chapter/section, using
-[pdf-tools](https://github.com/vedang/pdf-tools "Emacs pdf-tools") or
-[nov.el](https://depp.brause.cc/nov.el/ "Emacs nov.el").
-
-### Creating cloze type notes
-Cloze type note questions are formatted similarly to Anki's syntax, like so:
-> {c1:Cyproheptadine} is a(n) {c2:5-HT2} receptor antagonist used to treat {c2:serotonin syndrome}
-
-
-*NOTE*: You can also format clozes like Anki if you so prefer; e.g
-`{{c1::Cyproheptadine}}`
-
-+ For each `cX`-tag there will be created a cloze type note, the above
- example creates 2 cloze type notes.
-
-+ Each `cX` tag can have multiple clozes, but each cloze must be a
- *UNIQUE* word (or a unique combination of words) in given note.
-
-## Customizing gnosis algorithm
-
-### `gnosis-algorithm-interval`
-
-This is a list of 2 numbers, for the first 2 intervals after a
-successful review. For example:
-
-``` emacs-lisp
-(setq gnosis-algorithm-interval '(1 3))
-```
-
-After first successfully reviewing a note, you will see it again
-tomorrow, if you successfully review said note again, the next review
-will be after 3 days.
-
-### `gnosis-algorithm-ef`
-
-This is gnosis "easiness factor", it's basically a list that consists
-of 3 items. The first item is the increase factor, used to increase
-the easiness factor upon successful review. Second item refers to the
-decrease factor, used to decrease the easiness factor upon an
-unsuccessful review. The third item is the initial total easiness
-factor, used to calculate the next interval.
-
-The basic's of how this is used is that it's being multiplied with the
-last interval, e.g if you last reviewed a note 6 days ago, and the
-easiness factor of this note is 2.0, your next interval would be 6 *
-2.0. The next easiness will be 2.0 + increase-factor as well.
-
-For example:
-
-``` emacs-lisp
-(setq gnosis-algorithm-ef '(0.3 0.3 1.3))
-```
-
-### `gnsois-algorithm-ff`
-
-This is the value of gnosis forgetting factor(ff), it needs to be a floating number below 1. The 101 is that it's used to calculate the next interval upon an unsuccessful review, by being multiplied with last interval, if for a note with a value of last-interval of 6 days and a ff of 0.5, upon an unsuccessful review the next interval will be 6 * 0.5
-
-For example:
-
-``` emacs-lisp
-(setq gnosis-algorithm-ff 0.5)
-```
++ [User Manual](https://thanosapollo.org/user-manual/gnosis/)
diff --git a/doc/gnosis.info b/doc/gnosis.info
new file mode 100644
index 0000000..fe0338a
--- /dev/null
+++ b/doc/gnosis.info
@@ -0,0 +1,350 @@
+This is gnosis.info, produced by makeinfo version 7.1 from gnosis.texi.
+
+INFO-DIR-SECTION Emacs misc features
+START-INFO-DIR-ENTRY
+* Gnosis (γνῶσις): (gnosis). Spaced Repetition System For Note Taking And Self-Testing.
+END-INFO-DIR-ENTRY
+
+
+File: gnosis.info, Node: Top, Next: Introduction, Up: (dir)
+
+Gnosis User Manual
+******************
+
+Gnosis (γνῶσις), pronounced "noh-sis", _meaning knowledge in Greek_, is
+a spaced repetition system implementation for note taking and self
+testing.
+
+This manual is written for Gnosis version 0.1.3, released on 2023-01-18.
+
+ • Official manual: <https://thanosapollo.org/user-manual/gnosis>
+ • Git repositories:
+ • main: <https://git.thanosapollo.org/gnosis>
+ • sourcehut (mirror): <https://git.sr.ht/~thanosapollo/gnosis>
+
+* Menu:
+
+* Introduction::
+* Installation::
+* Adding notes::
+* Note Types::
+* Customization::
+
+-- The Detailed Node Listing --
+
+Installation
+
+* Using straight.el: Using straightel.
+* Installing manually from source::
+
+Note Types
+
+* Cloze::
+* Basic Type::
+* Double::
+* MCQ (Multiple Choice Question)::
+* y-or-n::
+
+Customization
+
+* Gnosis Algorithm Initial Interval::
+* Gnosis Algorithm Easiness Factor::
+* Gnosis Algorithm Forgetting Factor::
+
+
+
+File: gnosis.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top
+
+1 Introduction
+**************
+
+Gnosis is a spaced repetition note taking and self testing system, where
+notes are taken in a Question/Answer/Explanation-like format & reviewed
+in spaced intervals.
+
+ Gnosis can help you better understand and retain the material by
+encouraging active engagement. It also provides a clear structure for
+your notes & review sessions, making it easier to study.
+
+
+File: gnosis.info, Node: Installation, Next: Adding notes, Prev: Introduction, Up: Top
+
+2 Installation
+**************
+
+Gnosis is not currently available in any ELPA, the recommended way to
+install gnosis is via straight.el:
+
+ <https://github.com/radian-software/straight.el>
+
+* Menu:
+
+* Using straight.el: Using straightel.
+* Installing manually from source::
+
+
+File: gnosis.info, Node: Using straightel, Next: Installing manually from source, Up: Installation
+
+2.1 Using straight.el
+=====================
+
+If you have not installed straight.el, follow the instructions here:
+
+ <https://github.com/radian-software/straight.el>
+
+ Once you have installed straight.el, you can install gnosis using the
+following emacs lisp snippet:
+
+ (straight-use-package
+ '(gnosis :type git
+ :host nil
+ :repo "https://git.thanosapollo.org/gnosis"))
+
+
+File: gnosis.info, Node: Installing manually from source, Prev: Using straightel, Up: Installation
+
+2.2 Installing manually from source
+===================================
+
+Gnosis depends on the ‘compat’ & ‘emacsql’ libraries which are available
+from MELPA. Install them using ‘M-x package-install RET <package> RET’
+or you may also install them manually from their repository.
+
+ • Clone gnosis repository
+
+ $ git clone https://git.thanosapollo.org/gnosis ~/.emacs.d/site-lisp/gnosis
+
+ • Add this to your emacs configuration
+
+ (add-to-list 'load-path "~/.emacs.d/site-lisp/gnosis")
+ (load-file "~/.emacs.d/site-lisp/gnosis/gnosis.el")
+
+
+File: gnosis.info, Node: Adding notes, Next: Note Types, Prev: Installation, Up: Top
+
+3 Adding notes
+**************
+
+Creating notes for gnosis can be done interactively with: ‘M-x
+gnosis-add-note’
+
+ Advanced/Power users may prefer to use ‘gnosis-add-note--TYPE’
+
+ Example:
+
+ (gnosis-add-note--basic :deck "DECK-NAME"
+ :question "Your Question"
+ :answer "Answer"
+ :hint "hint"
+ :extra "Explanation"
+ :image "Image displayed before user-input" ;; Optional
+ :second-image "Image displayed after user-input" ;; Optional
+ :tags '("tag1" "tag2"))
+
+ By default, the value of image and second image is nil. Their value
+must a string, the path of an image, from inside ‘gnosis-images-dir’.
+
+ Each note type has a ‘gnosis-add-note-TYPE’ that is used
+interactively & a "hidden function" ‘gnosis-add-note--TYPE’ that handles
+all the logic.
+
+ Every note type has these values in common:
+
+ • ‘extra’ string value, extra information/explanation displayed after
+ user-input
+ • ‘image’ Image displayed _before_ user input
+ • ‘second-image’ Image displayed _after_ user input
+
+ The following sections will cover the important differences you have
+to know when creating notes.
+
+
+File: gnosis.info, Node: Note Types, Next: Customization, Prev: Adding notes, Up: Top
+
+4 Note Types
+************
+
+* Menu:
+
+* Cloze::
+* Basic Type::
+* Double::
+* MCQ (Multiple Choice Question)::
+* y-or-n::
+
+
+File: gnosis.info, Node: Cloze, Next: Basic Type, Up: Note Types
+
+4.1 Cloze
+=========
+
+A cloze note type is a format where you create sentences or paragraphs
+with "missing" words. Almost all note types can be written as a cloze
+type in a way. Ideal type for memorizing definitions.
+
+ To get the most out of gnosis, you have to become familiar with cloze
+type notes.
+
+ You can create a cloze note type using ‘M-x gnosis-add-note’ and
+selecting ‘Cloze’, the question should be formatted like this:
+
+ {c1:Cyproheptadine} is a(n) {c2:5-HT2} receptor antagonist used to
+ treat {c2:serotonin syndrome}
+
+ You can also format clozes like Anki if you prefer; e.g
+‘{{c1::Cyproheptadine}}’
+
+ • For each 'cX'-tag there will be created a cloze type note, the
+ above example creates 2 cloze type notes.
+
+ • Each 'cX' tag can have multiple clozes, but each cloze must be a
+ *UNIQUE* word (or a unique combination of words) in given note.
+
+
+File: gnosis.info, Node: Basic Type, Next: Double, Prev: Cloze, Up: Note Types
+
+4.2 Basic Type
+==============
+
+Basic note type is a simple question/answer note, where the user first
+sees a "main" part, which is usually a question, and he is prompted to
+input the answer.
+
+
+File: gnosis.info, Node: Double, Next: MCQ (Multiple Choice Question), Prev: Basic Type, Up: Note Types
+
+4.3 Double
+==========
+
+Double note type, is essentially a note that generates 2 basic notes.
+The second one reverses question/answer.
+
+ Ideal for vocabulary acquisition, creating vocabulary/translation
+notes for a foreign language.
+
+
+File: gnosis.info, Node: MCQ (Multiple Choice Question), Next: y-or-n, Prev: Double, Up: Note Types
+
+4.4 MCQ (Multiple Choice Question)
+==================================
+
+MCQ note type, consists of a "stem" part that is displayed, and
+"options" for the user to select the right one.
+
+ Answer must be the index NUMBER of the correct answer from OPTIONS.
+
+ Ideal for self testing & simulating exams
+
+
+File: gnosis.info, Node: y-or-n, Prev: MCQ (Multiple Choice Question), Up: Note Types
+
+4.5 y-or-n
+==========
+
+y-or-n (yes or no) note type, user is presented with a question and
+prompted to enter character "y" or "n".
+
+ When using the hidden function ‘gnosis-add-note--y-or-n’, note that
+the ANSWER must be either 121 (‘y’) or 110 (‘n’), as those correspond to
+the character values used to represent them.
+
+
+File: gnosis.info, Node: Customization, Prev: Note Types, Up: Top
+
+5 Customization
+***************
+
+* Menu:
+
+* Gnosis Algorithm Initial Interval::
+* Gnosis Algorithm Easiness Factor::
+* Gnosis Algorithm Forgetting Factor::
+
+
+File: gnosis.info, Node: Gnosis Algorithm Initial Interval, Next: Gnosis Algorithm Easiness Factor, Up: Customization
+
+5.1 Gnosis Algorithm Initial Interval
+=====================================
+
+‘gnosis-algorithm-interval’ is a list of 2 numbers, representing the
+first two initial intervals for successful reviews.
+
+ Example:
+
+ (setq gnosis-algorithm-interval '(1 3))
+
+ Using the above example, after first successfully reviewing a note,
+you will see it again tomorrow, if you successfully review said note
+again, the next review will be after 3 days.
+
+
+File: gnosis.info, Node: Gnosis Algorithm Easiness Factor, Next: Gnosis Algorithm Forgetting Factor, Prev: Gnosis Algorithm Initial Interval, Up: Customization
+
+5.2 Gnosis Algorithm Easiness Factor
+====================================
+
+‘gnosis-algorithm-ef’ is a list that consists of 3 items.
+
+ The first item is the increase factor, used to increase the easiness
+factor upon successful review.
+
+ Second item refers to the decrease factor, used to decrease the
+easiness factor upon an unsuccessful review.
+
+ The third item is the initial total easiness factor, used to
+calculate the next interval.
+
+ The basic's of how this is used is that it's being multiplied with
+the last interval upon a successful review, e.g if you last reviewed a
+note 6 days ago, and the easiness factor of this note is 2.0, your next
+interval would be 6 * 2.0 & the total easiness factor would be 2.0 +
+increase-factor as well.
+
+ Example:
+
+ (setq gnosis-algorithm-ef '(0.3 0.3 1.3))
+
+
+File: gnosis.info, Node: Gnosis Algorithm Forgetting Factor, Prev: Gnosis Algorithm Easiness Factor, Up: Customization
+
+5.3 Gnosis Algorithm Forgetting Factor
+======================================
+
+‘gnosis-algorithm-ff’ is a floating number below 1.
+
+ It's used to calculate the next interval upon an unsuccessful review,
+by being multiplied with last interval.
+
+ Example:
+
+ (setq gnosis-algorithm-ff 0.5)
+
+ For a note with a value of last-interval of 6 days and a ff of 0.5,
+upon an unsuccessful review the next interval will be 6 * 0.5
+
+
+
+Tag Table:
+Node: Top246
+Node: Introduction1249
+Node: Installation1729
+Node: Using straightel2098
+Node: Installing manually from source2614
+Node: Adding notes3303
+Node: Note Types4729
+Node: Cloze4941
+Node: Basic Type5914
+Node: Double6192
+Node: MCQ (Multiple Choice Question)6538
+Node: y-or-n6947
+Node: Customization7373
+Node: Gnosis Algorithm Initial Interval7602
+Node: Gnosis Algorithm Easiness Factor8174
+Node: Gnosis Algorithm Forgetting Factor9159
+
+End Tag Table
+
+
+Local Variables:
+coding: utf-8
+End:
diff --git a/doc/gnosis.org b/doc/gnosis.org
new file mode 100644
index 0000000..8d23a30
--- /dev/null
+++ b/doc/gnosis.org
@@ -0,0 +1,235 @@
+#+TITLE: Gnosis User Manual
+#+AUTHOR: Thanos Apollo
+#+language: en
+#+options: ':t toc:nil author:t email:t num:t
+#+startup: content
+#+macro: stable-version 0.1.3
+#+macro: release-date 2023-01-18
+#+macro: development-version 0.1.4-dev
+#+macro: file @@texinfo:@file{@@$1@@texinfo:}@@
+#+macro: space @@texinfo:@: @@
+#+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@
+#+macro: file @@texinfo:@file{@@$1@@texinfo:}@@
+#+macro: space @@texinfo:@: @@
+#+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@
+#+texinfo_filename: gnosis.info
+#+texinfo_dir_category: Emacs misc features
+#+texinfo_dir_title: Gnosis (γνῶσις): (gnosis)
+#+texinfo_dir_desc: Spaced Repetition System For Note Taking And Self-Testing
+#+texinfo_header: @set MAINTAINERSITE @uref{https://thanosapollo.org,maintainer webpage}
+#+texinfo_header: @set MAINTAINER Thanos Apollo
+#+texinfo_header: @set MAINTAINEREMAIL @email{[email protected]}
+#+texinfo_header: @set MAINTAINERCONTACT @uref{mailto:[email protected],contact the maintainer}
+
+
+Gnosis (γνῶσις), pronounced "noh-sis", /meaning knowledge in Greek/, is
+a spaced repetition system implementation for note taking and self
+testing.
+
+#+texinfo: @noindent
+This manual is written for Gnosis version {{{stable-version}}}, released on {{{release-date}}}.
+
++ Official manual: <https://thanosapollo.org/user-manual/gnosis>
++ Git repositories:
+ + main: <https://git.thanosapollo.org/gnosis>
+ + sourcehut (mirror): <https://git.sr.ht/~thanosapollo/gnosis>
+
+#+texinfo: @insertcopying
+
+* Introduction
+Gnosis is a spaced repetition note taking and self testing system,
+where notes are taken in a Question/Answer/Explanation-like format &
+reviewed in spaced intervals.
+
+Gnosis can help you better understand and retain the material by
+encouraging active engagement. It also provides a clear structure for
+your notes & review sessions, making it easier to study.
+
+* Installation
+
+Gnosis is not currently available in any ELPA, the recommended way to
+install gnosis is via straight.el:
+
+ <https://github.com/radian-software/straight.el>
+
+** Using straight.el
+If you have not installed straight.el, follow the instructions here:
+
+ <https://github.com/radian-software/straight.el>
+
+Once you have installed straight.el, you can install gnosis using the
+following emacs lisp snippet:
+
+#+begin_src emacs-lisp
+ (straight-use-package
+ '(gnosis :type git
+ :host nil
+ :repo "https://git.thanosapollo.org/gnosis"))
+#+end_src
+
+** Installing manually from source
+Gnosis depends on the ~compat~ & ~emacsql~ libraries which are available
+from MELPA. Install them using ~M-x package-install RET <package> RET~
+or you may also install them manually from their repository.
+
++ Clone gnosis repository
+
+ #+begin_src shell
+ $ git clone https://git.thanosapollo.org/gnosis ~/.emacs.d/site-lisp/gnosis
+ #+end_src
+
++ Add this to your emacs configuration
+
+ #+begin_src emacs-lisp
+ (add-to-list 'load-path "~/.emacs.d/site-lisp/gnosis")
+ (load-file "~/.emacs.d/site-lisp/gnosis/gnosis.el")
+ #+end_src
+
+* Adding notes
+Creating notes for gnosis can be done interactively with:
+ =M-x gnosis-add-note=
+
+
+Advanced/Power users may prefer to use =gnosis-add-note--TYPE=
+
+Example:
+
+#+begin_src emacs-lisp
+ (gnosis-add-note--basic :deck "DECK-NAME"
+ :question "Your Question"
+ :answer "Answer"
+ :hint "hint"
+ :extra "Explanation"
+ :image "Image displayed before user-input" ;; Optional
+ :second-image "Image displayed after user-input" ;; Optional
+ :tags '("tag1" "tag2"))
+#+end_src
+
+By default, the value of image and second image is nil. Their value
+must a string, the path of an image, from inside ~gnosis-images-dir~.
+
+Each note type has a =gnosis-add-note-TYPE= that is used
+interactively & a "hidden function" =gnosis-add-note--TYPE= that handles
+all the logic.
+
+Every note type has these values in common:
+
+ + ~extra~ string value, extra information/explanation displayed after user-input
+ + ~image~ Image displayed /before/ user input
+ + ~second-image~ Image displayed /after/ user input
+
+The following sections will cover the important differences you have
+to know when creating notes.
+
+* Note Types
+** Cloze
+
+A cloze note type is a format where you create sentences or paragraphs
+with "missing" words. Almost all note types can be written as a cloze
+type in a way. Ideal type for memorizing definitions.
+
+To get the most out of gnosis, you have to become familiar with cloze type notes.
+
+You can create a cloze note type using =M-x gnosis-add-note= and
+selecting ~Cloze~, the question should be formatted like this:
+
+#+BEGIN_QUOTE
+{c1:Cyproheptadine} is a(n) {c2:5-HT2} receptor antagonist used to treat {c2:serotonin syndrome}
+#+END_QUOTE
+
+You can also format clozes like Anki if you prefer; e.g ~{{c1::Cyproheptadine}}~
+
++ For each `cX`-tag there will be created a cloze type note, the above
+ example creates 2 cloze type notes.
+
++ Each `cX` tag can have multiple clozes, but each cloze must be a
+ *UNIQUE* word (or a unique combination of words) in given note.
+
+** Basic Type
+
+Basic note type is a simple question/answer note, where the user first
+sees a "main" part, which is usually a question, and he is prompted to
+input the answer.
+
+** Double
+Double note type, is essentially a note that generates 2 basic notes.
+The second one reverses question/answer.
+
+Ideal for vocabulary acquisition, creating vocabulary/translation
+notes for a foreign language.
+
+** MCQ (Multiple Choice Question)
+MCQ note type, consists of a "stem" part that is displayed, and
+"options" for the user to select the right one.
+
+Answer must be the index NUMBER of the correct answer from OPTIONS.
+
+Ideal for self testing & simulating exams
+
+** y-or-n
+y-or-n (yes or no) note type, user is presented with a question and
+prompted to enter character "y" or "n".
+
+When using the hidden function =gnosis-add-note--y-or-n=, note that the
+ANSWER must be either 121 (~y~) or 110 (~n~), as those correspond to the
+character values used to represent them.
+
+* Customization
+** Gnosis Algorithm Initial Interval
+
+=gnosis-algorithm-interval= is a list of 2 numbers, representing the
+first two initial intervals for successful reviews.
+
+Example:
+
+#+begin_src emacs-lisp
+ (setq gnosis-algorithm-interval '(1 3))
+#+end_src
+
+Using the above example, after first successfully reviewing a note,
+you will see it again tomorrow, if you successfully review said note
+again, the next review will be after 3 days.
+
+** Gnosis Algorithm Easiness Factor
+
+=gnosis-algorithm-ef= is a list that consists of 3 items.
+
+The first item is the increase factor, used to increase the easiness
+factor upon successful review.
+
+Second item refers to the decrease factor, used to
+decrease the easiness factor upon an unsuccessful review.
+
+The third item is the initial total easiness factor, used to calculate
+the next interval.
+
+The basic's of how this is used is that it's being multiplied with the
+last interval upon a successful review, e.g if you last reviewed a
+note 6 days ago, and the easiness factor of this note is 2.0, your
+next interval would be 6 * 2.0 & the total easiness factor would be
+2.0 + increase-factor as well.
+
+Example:
+
+#+begin_src emacs-lisp
+ (setq gnosis-algorithm-ef '(0.3 0.3 1.3))
+#+end_src
+
+** Gnosis Algorithm Forgetting Factor
+
+=gnosis-algorithm-ff= is a floating number below 1.
+
+It's used to calculate the next interval upon an unsuccessful review,
+by being multiplied with last interval.
+
+
+
+Example:
+
+#+begin_src emacs-lisp
+ (setq gnosis-algorithm-ff 0.5)
+#+end_src
+
+For a note with a value of last-interval of 6 days and a ff of 0.5,
+upon an unsuccessful review the next interval will be 6 * 0.5
diff --git a/doc/gnosis.texi b/doc/gnosis.texi
new file mode 100644
index 0000000..58c7f4e
--- /dev/null
+++ b/doc/gnosis.texi
@@ -0,0 +1,324 @@
+\input texinfo @c -*- texinfo -*-
+@c %**start of header
+@setfilename gnosis.info
+@settitle Gnosis User Manual
+@documentencoding UTF-8
+@documentlanguage en
+@set MAINTAINERSITE @uref{https://thanosapollo.org,maintainer webpage}
+@set MAINTAINER Thanos Apollo
+@set MAINTAINEREMAIL @email{[email protected]}
+@set MAINTAINERCONTACT @uref{mailto:[email protected],contact the maintainer}
+@c %**end of header
+
+@dircategory Emacs misc features
+@direntry
+* Gnosis (γνῶσις): (gnosis). Spaced Repetition System For Note Taking And Self-Testing.
+@end direntry
+
+@finalout
+@titlepage
+@title Gnosis User Manual
+@author Thanos Apollo (@email{public@@thanosapollo.org})
+@end titlepage
+
+@ifnottex
+@node Top
+@top Gnosis User Manual
+
+Gnosis (γνῶσις), pronounced ``noh-sis'', @emph{meaning knowledge in Greek}, is
+a spaced repetition system implementation for note taking and self
+testing.
+
+@noindent
+This manual is written for Gnosis version 0.1.3, released on 2023-01-18.
+
+@itemize
+@item
+Official manual: @uref{https://thanosapollo.org/user-manual/gnosis}
+@item
+Git repositories:
+@itemize
+@item
+main: @uref{https://git.thanosapollo.org/gnosis}
+@item
+sourcehut (mirror): @uref{https://git.sr.ht/~thanosapollo/gnosis}
+@end itemize
+@end itemize
+
+@insertcopying
+
+@end ifnottex
+
+@menu
+* Introduction::
+* Installation::
+* Adding notes::
+* Note Types::
+* Customization::
+
+@detailmenu
+--- The Detailed Node Listing ---
+
+Installation
+
+* Using straight.el: Using straightel.
+* Installing manually from source::
+
+Note Types
+
+* Cloze::
+* Basic Type::
+* Double::
+* MCQ (Multiple Choice Question)::
+* y-or-n::
+
+Customization
+
+* Gnosis Algorithm Initial Interval::
+* Gnosis Algorithm Easiness Factor::
+* Gnosis Algorithm Forgetting Factor::
+
+@end detailmenu
+@end menu
+
+@node Introduction
+@chapter Introduction
+
+Gnosis is a spaced repetition note taking and self testing system,
+where notes are taken in a Question/Answer/Explanation-like format &
+reviewed in spaced intervals.
+
+Gnosis can help you better understand and retain the material by
+encouraging active engagement. It also provides a clear structure for
+your notes & review sessions, making it easier to study.
+
+@node Installation
+@chapter Installation
+
+Gnosis is not currently available in any ELPA, the recommended way to
+install gnosis is via straight.el:
+
+@uref{https://github.com/radian-software/straight.el}
+
+@menu
+* Using straight.el: Using straightel.
+* Installing manually from source::
+@end menu
+
+@node Using straightel
+@section Using straight.el
+
+If you have not installed straight.el, follow the instructions here:
+
+@uref{https://github.com/radian-software/straight.el}
+
+Once you have installed straight.el, you can install gnosis using the
+following emacs lisp snippet:
+
+@lisp
+(straight-use-package
+ '(gnosis :type git
+ :host nil
+ :repo "https://git.thanosapollo.org/gnosis"))
+@end lisp
+
+@node Installing manually from source
+@section Installing manually from source
+
+Gnosis depends on the @code{compat} & @code{emacsql} libraries which are available
+from MELPA@. Install them using @code{M-x package-install RET <package> RET}
+or you may also install them manually from their repository.
+
+@itemize
+@item
+Clone gnosis repository
+
+@example
+$ git clone https://git.thanosapollo.org/gnosis ~/.emacs.d/site-lisp/gnosis
+@end example
+
+@item
+Add this to your emacs configuration
+
+@lisp
+(add-to-list 'load-path "~/.emacs.d/site-lisp/gnosis")
+(load-file "~/.emacs.d/site-lisp/gnosis/gnosis.el")
+@end lisp
+@end itemize
+
+@node Adding notes
+@chapter Adding notes
+
+Creating notes for gnosis can be done interactively with:
+ @samp{M-x gnosis-add-note}
+
+
+Advanced/Power users may prefer to use @samp{gnosis-add-note--TYPE}
+
+Example:
+
+@lisp
+(gnosis-add-note--basic :deck "DECK-NAME"
+ :question "Your Question"
+ :answer "Answer"
+ :hint "hint"
+ :extra "Explanation"
+ :image "Image displayed before user-input" ;; Optional
+ :second-image "Image displayed after user-input" ;; Optional
+ :tags '("tag1" "tag2"))
+@end lisp
+
+By default, the value of image and second image is nil. Their value
+must a string, the path of an image, from inside @code{gnosis-images-dir}.
+
+Each note type has a @samp{gnosis-add-note-TYPE} that is used
+interactively & a ``hidden function'' @samp{gnosis-add-note--TYPE} that handles
+all the logic.
+
+Every note type has these values in common:
+
+@itemize
+@item
+@code{extra} string value, extra information/explanation displayed after user-input
+@item
+@code{image} Image displayed @emph{before} user input
+@item
+@code{second-image} Image displayed @emph{after} user input
+@end itemize
+
+The following sections will cover the important differences you have
+to know when creating notes.
+
+@node Note Types
+@chapter Note Types
+
+@node Cloze
+@section Cloze
+
+A cloze note type is a format where you create sentences or paragraphs
+with ``missing'' words. Almost all note types can be written as a cloze
+type in a way. Ideal type for memorizing definitions.
+
+To get the most out of gnosis, you have to become familiar with cloze type notes.
+
+You can create a cloze note type using @samp{M-x gnosis-add-note} and
+selecting @code{Cloze}, the question should be formatted like this:
+
+@quotation
+@{c1:Cyproheptadine@} is a(n) @{c2:5-HT2@} receptor antagonist used to treat @{c2:serotonin syndrome@}
+
+@end quotation
+
+You can also format clozes like Anki if you prefer; e.g @code{@{@{c1::Cyproheptadine@}@}}
+
+@itemize
+@item
+For each `cX`-tag there will be created a cloze type note, the above
+example creates 2 cloze type notes.
+
+@item
+Each `cX` tag can have multiple clozes, but each cloze must be a
+@strong{UNIQUE} word (or a unique combination of words) in given note.
+@end itemize
+
+@node Basic Type
+@section Basic Type
+
+Basic note type is a simple question/answer note, where the user first
+sees a ``main'' part, which is usually a question, and he is prompted to
+input the answer.
+
+@node Double
+@section Double
+
+Double note type, is essentially a note that generates 2 basic notes.
+The second one reverses question/answer.
+
+Ideal for vocabulary acquisition, creating vocabulary/translation
+notes for a foreign language.
+
+@node MCQ (Multiple Choice Question)
+@section MCQ (Multiple Choice Question)
+
+MCQ note type, consists of a ``stem'' part that is displayed, and
+``options'' for the user to select the right one.
+
+Answer must be the index NUMBER of the correct answer from OPTIONS@.
+
+Ideal for self testing & simulating exams
+
+@node y-or-n
+@section y-or-n
+
+y-or-n (yes or no) note type, user is presented with a question and
+prompted to enter character ``y'' or ``n''.
+
+When using the hidden function @samp{gnosis-add-note--y-or-n}, note that the
+ANSWER must be either 121 (@code{y}) or 110 (@code{n}), as those correspond to the
+character values used to represent them.
+
+@node Customization
+@chapter Customization
+
+@node Gnosis Algorithm Initial Interval
+@section Gnosis Algorithm Initial Interval
+
+@samp{gnosis-algorithm-interval} is a list of 2 numbers, representing the
+first two initial intervals for successful reviews.
+
+Example:
+
+@lisp
+(setq gnosis-algorithm-interval '(1 3))
+@end lisp
+
+Using the above example, after first successfully reviewing a note,
+you will see it again tomorrow, if you successfully review said note
+again, the next review will be after 3 days.
+
+@node Gnosis Algorithm Easiness Factor
+@section Gnosis Algorithm Easiness Factor
+
+@samp{gnosis-algorithm-ef} is a list that consists of 3 items.
+
+The first item is the increase factor, used to increase the easiness
+factor upon successful review.
+
+Second item refers to the decrease factor, used to
+decrease the easiness factor upon an unsuccessful review.
+
+The third item is the initial total easiness factor, used to calculate
+the next interval.
+
+The basic's of how this is used is that it's being multiplied with the
+last interval upon a successful review, e.g if you last reviewed a
+note 6 days ago, and the easiness factor of this note is 2.0, your
+next interval would be 6 * 2.0 & the total easiness factor would be
+2.0 + increase-factor as well.
+
+Example:
+
+@lisp
+(setq gnosis-algorithm-ef '(0.3 0.3 1.3))
+@end lisp
+
+@node Gnosis Algorithm Forgetting Factor
+@section Gnosis Algorithm Forgetting Factor
+
+@samp{gnosis-algorithm-ff} is a floating number below 1.
+
+It's used to calculate the next interval upon an unsuccessful review,
+by being multiplied with last interval.
+
+
+
+Example:
+
+@lisp
+(setq gnosis-algorithm-ff 0.5)
+@end lisp
+
+For a note with a value of last-interval of 6 days and a ff of 0.5,
+upon an unsuccessful review the next interval will be 6 * 0.5
+
+@bye
diff --git a/gnosis-algorithm.el b/gnosis-algorithm.el
index e6a2b1f..596bc7c 100644
--- a/gnosis-algorithm.el
+++ b/gnosis-algorithm.el
@@ -41,7 +41,7 @@ Note: `gnosis-algorithm-interval' is ignored after 10 TOTAL reviews or
when ef is above > 3.0, which should only be the case for customized
notes/review sessions."
:group 'gnosis
- :type 'list)
+ :type '(list integer))
(defcustom gnosis-algorithm-ef '(0.3 0.3 1.3)
"Gnosis easiness factor.
@@ -52,7 +52,7 @@ Third item : Starting total ef
Note: Starting total ef should not be above 3.0"
:group 'gnosis
- :type 'list)
+ :type '(list float))
(defcustom gnosis-algorithm-ff 0.5
"Gnosis forgetting factor.
@@ -97,23 +97,24 @@ The structure of the given date is (YEAR MONTH DAY)."
(+ ef (car gnosis-algorithm-ef)))
(t (error "Invalid quality score passed to gnosis-algorithm-e-factor"))))
-;; This should be further tested for notes with last-interval of 0 when success 0
-;; For future versions of this algorithm, we should also calculate
-;; failures in row to have "leech" like notes as well.
-;; TODO: Use initial-interval value instead gnosis-algorithm-interval
-(defun gnosis-algorithm-next-interval (last-interval n ef success ff successful-reviews)
+
+(cl-defun gnosis-algorithm-next-interval (&key last-interval review-num ef success failure-factor successful-reviews successful-reviews-c fails-c fails-t initial-interval)
"Calculate next interval.
- LAST-INTERVAL : The number of days since the item was last reviewed.
-- N : Number of times the item has been reviewed.
+-review-num: Number of times the item has been reviewed.
- EF : Easiness Factor.
- SUCCESS : Success of the recall, ranges from 0 (unsuccessful) to 1
(successful).
- FF: Failure factor
- SUCCESSFUL-REVIEWS : Number of successful reviews.
+- SUCCESSFULL-REVIEWS-C: Successful reviews in a row.
+- FAILS-C: Failed reviews in a row.
+- FAILS-T: Total failed reviews.
+- INITIAL-INTERVAL: Initial intervals for successful reviews.
Returns a list of: (INTERVAL N EF) where,
- Next review date in (yyyy mm dd) format.
-- N : Incremented by 1.
+- REVIEW-NUM: Incremented by 1.
- EF : Modified based on the recall success for the item."
(cl-assert (and (>= success 0)
(<= success 1)))
@@ -132,23 +133,41 @@ Returns a list of: (INTERVAL N EF) where,
;; First successful review -> first interval
((and (= successful-reviews 0)
(= success 1)
- (< n 10)
+ (< review-num 10)
(< ef 3.0))
- (car gnosis-algorithm-interval))
+ (car initial-interval))
;; Second successful review -> second interval
((and (= successful-reviews 1)
- (< n 10)
+ (< review-num 10)
(= success 1)
- (< ef 3.0))
- (cadr gnosis-algorithm-interval))
+ (< ef 3.0)
+ (= fails-c 0)
+ (cadr initial-interval)))
+ ;; When successful-reviews-c is above 3, use 150% or 180%
+ ;; of ef depending on the value of successful-reviews
+ ((and (= success 1)
+ (>= successful-reviews-c 3))
+ (* (* ef (if (>= successful-reviews 10) 1.8 1.5)) last-interval))
+ ((and (= success 0)
+ (> fails-c 3))
+ ;; When fails-c is above 3, use 150% or 180% of
+ ;; failure-factor depending on the value of total failed
+ ;; reviews. It should not be above 0.8
+ (* (max (min 0.8 (* failure-factor (if (>= fails-t 10) 1.8 1.5)))
+ failure-factor)
+ last-interval))
;; For custom review sessions.
+ ;; When successful-reviews-c is above 0, multiply its value
+ ;; with ef
((and (= last-interval 0)
(= success 1))
- (* ef 1))
+ (* ef (if (> successful-reviews-c 0)
+ successful-reviews-c
+ 1)))
;; For everything else
(t (if (= success 1)
(* ef last-interval)
- (* ff last-interval))))))
+ (* failure-factor last-interval))))))
(list (gnosis-algorithm-date (round interval)) next-ef)))
(provide 'gnosis-algorithm)
diff --git a/gnosis.el b/gnosis.el
index 752d828..7ddeb30 100644
--- a/gnosis.el
+++ b/gnosis.el
@@ -56,8 +56,8 @@
:type 'directory
:group 'gnosis)
-(defcustom gnosis-cloze-char "__"
- "Gnosis cloze character."
+(defcustom gnosis-cloze-string "__"
+ "Gnosis string to represent a cloze."
:type 'string
:group 'gnosis)
@@ -69,7 +69,7 @@
(if (not (file-directory-p gnosis-dir))
(gnosis-db-init)
(emacsql-sqlite (concat (file-name-as-directory gnosis-dir) "gnosis.db")))
- "Gnosis database file. WARNING: Do not change this value!")
+ "Gnosis database file.")
(defvar gnosis-testing nil
"When t, warn user he is in a testing environment.")
@@ -179,12 +179,6 @@ Example:
"From TABLE use where to delete VALUE."
(emacsql gnosis-db `[:delete :from ,table :where ,value]))
-(defmacro with-gnosis-buffer (&rest body)
- "Execute BODY in gnosis buffer."
- `(with-current-buffer (switch-to-buffer (get-buffer-create "*gnosis*"))
- (gnosis-mode)
- ,@body))
-
(cl-defun gnosis-completing-read (prompt options info &optional (face-for-info 'font-lock-doc-face))
"A version of `completing-read' with text properties, padding & choosable face.
Returns selected option from OPTIONS.
@@ -214,28 +208,25 @@ FACE-FOR-INFO is the face used to display info for option."
if (= i index) collect new-item
else collect item))
-(defun gnosis-display--question (id)
+(defun gnosis-display-question (id)
"Display main row for note ID."
(let ((question (gnosis-get 'main 'notes `(= id ,id))))
- (with-gnosis-buffer
(erase-buffer)
(fill-paragraph (insert (concat "\n"
- (propertize question 'face 'gnosis-face-main)))))))
+ (propertize question 'face 'gnosis-face-main))))))
-(defun gnosis-display--cloze-sentence (sentence clozes)
+(defun gnosis-display-cloze-sentence (sentence clozes)
"Display cloze sentence for SENTENCE with CLOZES."
- (with-gnosis-buffer
- (erase-buffer)
- (fill-paragraph
- (insert
- (concat "\n"
- (gnosis-cloze-replace-words sentence clozes (propertize gnosis-cloze-char 'face 'gnosis-face-cloze)))))))
-
-(defun gnosis-display--basic-answer (answer success user-input)
+ (erase-buffer)
+ (fill-paragraph
+ (insert
+ (concat "\n"
+ (gnosis-cloze-replace-words sentence clozes (propertize gnosis-cloze-string 'face 'gnosis-face-cloze))))))
+
+(defun gnosis-display-basic-answer (answer success user-input)
"Display ANSWER.
When SUCCESS nil, display USER-INPUT as well"
- (with-gnosis-buffer
(insert
(concat "\n\n"
(propertize "Answer:" 'face 'gnosis-face-directions)
@@ -246,7 +237,7 @@ When SUCCESS nil, display USER-INPUT as well"
(insert (concat "\n"
(propertize "Your answer:" 'face 'gnosis-face-directions)
" "
- (propertize user-input 'face 'gnosis-face-false))))))
+ (propertize user-input 'face 'gnosis-face-false)))))
(cl-defun gnosis-display-y-or-n-answer (&key answer success)
"Display y-or-n answer for note ID.
@@ -255,48 +246,43 @@ ANSWER is the correct answer, either y or n. Answer is either 121 or
110, which are the char values for y & n respectively
SUCCESS is t when user-input is correct, else nil"
(let ((answer (if (equal answer 121) "y" "n")))
- (with-gnosis-buffer
(insert
(concat "\n\n"
(propertize "Answer:" 'face 'gnosis-face-directions)
" "
- (propertize answer 'face (if success 'gnosis-face-correct 'gnosis-face-false)))))))
+ (propertize answer 'face (if success 'gnosis-face-correct 'gnosis-face-false))))))
-(defun gnosis-display--hint (hint)
+(defun gnosis-display-hint (hint)
"Display HINT."
- (with-gnosis-buffer
(goto-char (point-max))
(insert (concat
(propertize "\n\n-----\n" 'face 'gnosis-face-seperator)
- (propertize hint 'face 'gnosis-face-hint)))))
+ (propertize hint 'face 'gnosis-face-hint))))
-(cl-defun gnosis-display-cloze-reveal (&key (cloze-char gnosis-cloze-char) replace (success t) (face nil))
+(cl-defun gnosis-display-cloze-reveal (&key (cloze-char gnosis-cloze-string) replace (success t) (face nil))
"Replace CLOZE-CHAR with REPLACE.
If FACE nil, propertize replace using `gnosis-face-correct', or
`gnosis-face-false' when (not SUCCESS). Else use FACE value."
- (with-gnosis-buffer
(goto-char (point-min))
(search-forward cloze-char nil t)
(replace-match (propertize replace 'face (if (not face)
(if success 'gnosis-face-correct 'gnosis-face-false)
- face)))))
+ face))))
(cl-defun gnosis-display-cloze-user-answer (user-input &optional (false t))
"Display USER-INPUT answer for cloze note upon failed review.
If FALSE t, use gnosis-face-false face"
- (with-gnosis-buffer
(goto-char (point-max))
(insert (concat "\n\n"
(propertize "Your answer:" 'face 'gnosis-face-directions)
" "
- (propertize user-input 'face (if false 'gnosis-face-false 'gnosis-face-correct))))))
+ (propertize user-input 'face (if false 'gnosis-face-false 'gnosis-face-correct)))))
-(defun gnosis-display--correct-answer-mcq (answer user-choice)
+(defun gnosis-display-correct-answer-mcq (answer user-choice)
"Display correct ANSWER & USER-CHOICE for MCQ note."
- (with-gnosis-buffer
(insert (concat "\n\n"
(propertize "Correct Answer:" 'face 'gnosis-face-directions)
" "
@@ -306,41 +292,38 @@ If FALSE t, use gnosis-face-false face"
" "
(propertize user-choice 'face (if (string= answer user-choice)
'gnosis-face-correct
- 'gnosis-face-false))))))
+ 'gnosis-face-false)))))
-(defun gnosis-display--extra (id)
+(defun gnosis-display-extra (id)
"Display extra information for note ID."
(let ((extras (gnosis-get 'extra-notes 'extras `(= id ,id))))
- (with-gnosis-buffer
- (goto-char (point-max))
- (insert (propertize "\n\n-----\n" 'face 'gnosis-face-seperator))
- (fill-paragraph (insert (concat "\n" (propertize extras 'face 'gnosis-face-extra)))))))
+ (goto-char (point-max))
+ (insert (propertize "\n\n-----\n" 'face 'gnosis-face-seperator))
+ (fill-paragraph (insert (concat "\n" (propertize extras 'face 'gnosis-face-extra))))))
-(defun gnosis-display--image (id)
+(defun gnosis-display-image (id)
"Display image for note ID."
(let* ((img (gnosis-get 'images 'extras `(= id ,id)))
(path-to-image (concat (file-name-as-directory gnosis-images-dir) img))
(image (create-image path-to-image 'png nil :width 500 :height 300)))
(when img
- (with-gnosis-buffer
- (insert "\n\n")
- (insert-image image)))))
+ (insert "\n\n")
+ (insert-image image))))
-(defun gnosis-display--next-review (id)
+(defun gnosis-display-next-review (id)
"Display next interval for note ID."
(let ((interval (gnosis-get 'next-rev 'review-log `(= id ,id))))
- (with-gnosis-buffer
- (goto-char (point-max))
- (insert (concat "\n\n"
- (propertize "Next review:" 'face 'gnosis-face-directions)
- " "
- (propertize (format "%s" interval) 'face 'gnosis-face-next-review))))))
+ (goto-char (point-max))
+ (insert (concat "\n\n"
+ (propertize "Next review:" 'face 'gnosis-face-directions)
+ " "
+ (propertize (format "%s" interval) 'face 'gnosis-face-next-review)))))
(cl-defun gnosis--prompt (prompt &optional (downcase nil) (split nil))
"PROMPT user for input until `q' is given.
-The user is prompted to provide input for the 'PROMPT' message.
-Returns the list of non-'q' inputs in reverse order of their entry.
+The user is prompted to provide input for the PROMPT message.
+Returns the list of non-q inputs in reverse order of their entry.
Set DOWNCASE to t to downcase all input given.
Set SPLIT to t to split all input given."
@@ -395,8 +378,8 @@ When called with a prefix, unsuspends all notes in deck."
(suspend (if current-prefix-arg 0 1))
(note-count 0))
(cl-loop for note in notes
- do (progn (gnosis-update 'review-log `(= suspend ,suspend) `(= id ,(car note)))
- (setq note-count (1+ note-count)))
+ do (gnosis-update 'review-log `(= suspend ,suspend) `(= id ,(car note)))
+ (setq note-count (1+ note-count))
finally (if (equal suspend 0)
(message "Unsuspended %s notes" note-count)
(message "Suspended %s notes" note-count)))))
@@ -481,7 +464,7 @@ choice in the `CHOICES' list. Each note must correspond to one `DECK'.
Create a note type MCQ for specified deck, that consists of:
STEM: The question or problem statement
OPTIONS: Options for the user to select
-ANSWER: Answer is the NUMBER of the correct answer of OPTIONS.
+ANSWER: Answer is the index NUMBER of the correct answer from OPTIONS.
EXTRA: Information to display after user-input
TAGS: Used to organize notes
@@ -512,9 +495,9 @@ SUSPEND: Binary value of 0 & 1, when 1 note will be ignored."
(defun gnosis-add-note-basic ()
"Add note(s) of type `Basic' interactively to selected deck.
-Basic note type is a flashcard-like note, where user first sees a
-\"main\" part, which is usually a question, and he is prompted to
-input the answer.
+Basic note type is a simple question/answer note, where user first
+sees a \"main\" part, which is usually a question, and he is prompted
+to input the answer.
Refer to `gnosis-add-note--basic' for more."
(let ((deck (gnosis--get-deck-name)))
@@ -577,7 +560,7 @@ SECOND-IMAGE: Image to display after user-input."
(gnosis-add-note-fields deck "y-or-n" question hint answer extra tags suspend image second-image))
(defun gnosis-add-note-y-or-n ()
- "Add note(s) of type `y-or-n' interactively to selected deck.
+ "Add note(s) of type `y-or-n'.
refer to `gnosis-add-note--y-or-n' for more information about keyword values."
(let ((deck (gnosis--get-deck-name)))
@@ -861,10 +844,21 @@ SUCCESS is a binary value, 1 = success, 0 = failure.
Returns a list of the form ((yyyy mm dd) ef)."
(let ((ff gnosis-algorithm-ff)
(ef (nth 2 (gnosis-get 'ef 'review `(= id ,id))))
- (t-success (gnosis-get 't-success 'review-log `(= id ,id))))
- (gnosis-algorithm-next-interval (gnosis-review--get-offset id)
- (gnosis-get 'n 'review-log `(= id ,id))
- ef success ff t-success)))
+ (t-success (gnosis-get 't-success 'review-log `(= id ,id)))
+ (c-success (gnosis-get 'c-success 'review-log `(= id ,id)))
+ (c-fails (gnosis-get 'c-fails 'review-log `(= id ,id)))
+ (t-fails (gnosis-get 't-fails 'review-log `(= id ,id)))
+ (initial-interval (gnosis-get 'interval 'review `(= id ,id))))
+ (gnosis-algorithm-next-interval :last-interval (max (gnosis-review--get-offset id) 1) ;; last-interv always >=1
+ :review-num (gnosis-get 'n 'review-log `(= id ,id))
+ :ef ef
+ :success success
+ :failure-factor ff
+ :successful-reviews t-success
+ :successful-reviews-c c-success
+ :fails-c c-fails
+ :fails-t t-fails
+ :initial-interval initial-interval)))
(defun gnosis-review-due-notes--with-tags ()
"Return a list of due note tags."
@@ -917,45 +911,45 @@ SUCCESS is a binary value, 1 is for successful review."
(defun gnosis-review-mcq (id)
"Display multiple choice answers for question ID."
- (gnosis-display--image id)
- (gnosis-display--question id)
- (let* ((choices (gnosis-get 'options 'notes `(= id ,id)))
- (answer (nth (- (gnosis-get 'answer 'notes `(= id ,id)) 1) choices))
- (user-choice (gnosis-mcq-answer id)))
- (if (string= answer user-choice)
- (progn (gnosis-review--update id 1)
- (message "Correct!"))
- (gnosis-review--update id 0)
- (message "False"))
- (gnosis-display--correct-answer-mcq answer user-choice)
- (gnosis-display--extra id)
- (gnosis-display--next-review id)))
+ (gnosis-display-image id)
+ (gnosis-display-question id)
+ (let* ((choices (gnosis-get 'options 'notes `(= id ,id)))
+ (answer (nth (- (gnosis-get 'answer 'notes `(= id ,id)) 1) choices))
+ (user-choice (gnosis-mcq-answer id)))
+ (if (string= answer user-choice)
+ (progn (gnosis-review--update id 1)
+ (message "Correct!"))
+ (gnosis-review--update id 0)
+ (message "False"))
+ (gnosis-display-correct-answer-mcq answer user-choice)
+ (gnosis-display-extra id)
+ (gnosis-display-next-review id)))
(defun gnosis-review-basic (id)
"Review basic type note for ID."
- (gnosis-display--image id)
- (gnosis-display--question id)
- (gnosis-display--hint (gnosis-get 'options 'notes `(= id ,id)))
+ (gnosis-display-image id)
+ (gnosis-display-question id)
+ (gnosis-display-hint (gnosis-get 'options 'notes `(= id ,id)))
(let* ((answer (gnosis-get 'answer 'notes `(= id ,id)))
(user-input (read-string "Answer: "))
(success (gnosis-compare-strings answer user-input)))
- (gnosis-display--basic-answer answer success user-input)
- (gnosis-display--extra id)
+ (gnosis-display-basic-answer answer success user-input)
+ (gnosis-display-extra id)
(gnosis-review--update id (if success 1 0))
- (gnosis-display--next-review id)))
+ (gnosis-display-next-review id)))
(defun gnosis-review-y-or-n (id)
"Review y-or-n type note for ID."
- (gnosis-display--image id)
- (gnosis-display--question id)
- (gnosis-display--hint (gnosis-get 'options 'notes `(= id ,id)))
- (let* ((answer (gnosis-get 'answer 'notes `(= id ,id)))
- (user-input (read-char-choice "[y]es or [n]o: " '(?y ?n)))
- (success (equal answer user-input)))
- (gnosis-display-y-or-n-answer :answer answer :success success)
- (gnosis-display--extra id)
- (gnosis-review--update id (if success 1 0))
- (gnosis-display--next-review id)))
+ (gnosis-display-image id)
+ (gnosis-display-question id)
+ (gnosis-display-hint (gnosis-get 'options 'notes `(= id ,id)))
+ (let* ((answer (gnosis-get 'answer 'notes `(= id ,id)))
+ (user-input (read-char-choice "[y]es or [n]o: " '(?y ?n)))
+ (success (equal answer user-input)))
+ (gnosis-display-y-or-n-answer :answer answer :success success)
+ (gnosis-display-extra id)
+ (gnosis-review--update id (if success 1 0))
+ (gnosis-display-next-review id)))
(defun gnosis-review-cloze--input (cloze)
"Prompt for user input during cloze review.
@@ -978,9 +972,9 @@ Used to reveal all clozes left with `gnosis-face-cloze-unanswered' face."
(num 1)
(clozes-num (length clozes))
(hint (gnosis-get 'options 'notes `(= id ,id))))
- (gnosis-display--image id)
- (gnosis-display--cloze-sentence main clozes)
- (gnosis-display--hint hint)
+ (gnosis-display-image id)
+ (gnosis-display-cloze-sentence main clozes)
+ (gnosis-display-hint hint)
(cl-loop for cloze in clozes
do (let ((input (gnosis-review-cloze--input cloze)))
(if (equal (car input) t)
@@ -998,21 +992,23 @@ Used to reveal all clozes left with `gnosis-face-cloze-unanswered' face."
(cl-return)))
;; Update note after all clozes are revealed successfully
finally (gnosis-review--update id 1)))
- (gnosis-display--extra id)
- (gnosis-display--next-review id))
+ (gnosis-display-extra id)
+ (gnosis-display-next-review id))
(defun gnosis-review-note (id)
"Start review for note with value of id ID, if note is unsuspended."
(cond ((gnosis-suspended-p id)
(message "Note is suspended."))
(t
- (let ((type (gnosis-get 'type 'notes `(= id ,id))))
- (pcase type
- ("mcq" (gnosis-review-mcq id))
- ("basic" (gnosis-review-basic id))
- ("cloze" (gnosis-review-cloze id))
- ("y-or-n" (gnosis-review-y-or-n id))
- (_ (error "Malformed note type")))))))
+ (with-current-buffer (switch-to-buffer (get-buffer-create "*gnosis*"))
+ (let ((type (gnosis-get 'type 'notes `(= id ,id))))
+ (gnosis-mode)
+ (pcase type
+ ("mcq" (gnosis-review-mcq id))
+ ("basic" (gnosis-review-basic id))
+ ("cloze" (gnosis-review-cloze id))
+ ("y-or-n" (gnosis-review-y-or-n id))
+ (_ (error "Malformed note type"))))))))
(defun gnosis-review-commit (note-num)
"Commit review session on git repository.
@@ -1041,15 +1037,15 @@ NOTE-NUM: The number of notes reviewed in the session."
(message "No notes for review.")
(when (y-or-n-p (format "You have %s total notes for review, start session?" (length notes)))
(cl-loop for note in notes
- do (progn (gnosis-review-note note)
- (setf note-count (1+ note-count))
- (pcase (read-char-choice "Note Action: [n]ext, [s]uspend, [e]dit, [q]uit: " '(?n ?s ?e ?q))
- (?n nil)
- (?s (gnosis-suspend-note note))
- (?e (progn (gnosis-edit-note note)
- (recursive-edit)))
- (?q (progn (gnosis-review-commit note-count)
- (cl-return)))))
+ do (gnosis-review-note note)
+ (setf note-count (1+ note-count))
+ (pcase (read-char-choice "Note Action: [n]ext, [s]uspend, [e]dit, [q]uit: " '(?n ?s ?e ?q))
+ (?n nil)
+ (?s (gnosis-suspend-note note))
+ (?e (progn (gnosis-edit-note note)
+ (recursive-edit)))
+ (?q (progn (gnosis-review-commit note-count)
+ (cl-return))))
finally (gnosis-review-commit note-count))))))
@@ -1123,7 +1119,9 @@ changes."
(extra-notes ,extra-notes)
(image ,image)
(second-image ,second-image))
- do (cond ((numberp value)
+ do (cond ((equal field 'id)
+ (insert (format (concat ":%s " (propertize "%s" 'read-only t) "\n") field value)))
+ ((numberp value)
(insert (format ":%s %s\n" field value)))
((and (listp value)
(not (equal value nil)))
@@ -1264,7 +1262,7 @@ name and all notes formatted as nested lists"
(with-temp-file (concat filename ".el")
(insert "(gnosis-define-deck " "'" deck-name " '(")
(cl-loop for note in notes
- do (progn (insert "(") (gnosis-export-note note) (insert ")" "\n"))
+ do (insert "(") (gnosis-export-note note) (insert ")" "\n")
finally (insert "))")))))
;; TODO: Add defcustom to have suspended as 0 or 1 depending on
@@ -1379,7 +1377,7 @@ review."
;; Make sure gnosis-db is initialized
(setf gnosis-db (emacsql-sqlite (concat (file-name-as-directory gnosis-dir) "gnosis.db"))))
;; Create database tables
- (unless (length= (emacsql gnosis-db [:select name :from sqlite-master :where (= type table)]) 6)
+ (unless (= (length (emacsql gnosis-db [:select name :from sqlite-master :where (= type table)])) 6)
;; Enable foreign keys
(emacsql gnosis-db "PRAGMA foreign_keys = ON")
;; Gnosis version