diff options
-rw-r--r-- | README.md | 112 | ||||
-rw-r--r-- | doc/gnosis.info | 350 | ||||
-rw-r--r-- | doc/gnosis.org | 235 | ||||
-rw-r--r-- | doc/gnosis.texi | 324 | ||||
-rw-r--r-- | gnosis-algorithm.el | 51 | ||||
-rw-r--r-- | gnosis.el | 234 |
6 files changed, 1063 insertions, 243 deletions
@@ -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 +#+email: [email protected] +#+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) @@ -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 |