summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThanos Apollo <[email protected]>2024-07-15 12:08:50 +0300
committerThanos Apollo <[email protected]>2024-07-15 12:08:50 +0300
commit8fffcd9bff83652f03bc38e0a26bb17c98a02858 (patch)
tree16f7e9ac7705ba0a5147709ade5dd71f19df0821
parent9f678e624d7e89478d0090826f813d05bb811e27 (diff)
parent9f603ed091b950fe4fe3c327b52bb0a7e66d570c (diff)
Release version 0.3.10.3.1
- Major refactoring of cloze note types - Addition of hints per cloze & refactoring of displaying cloze notes - Add randomized deck ids - Minor changes on demo - Minor bug fixes
-rw-r--r--doc/gnosis.info71
-rw-r--r--doc/gnosis.org29
-rw-r--r--doc/gnosis.texi26
-rw-r--r--gnosis-test.el2
-rw-r--r--gnosis.el282
5 files changed, 244 insertions, 166 deletions
diff --git a/doc/gnosis.info b/doc/gnosis.info
index f9296f3..6bab4f5 100644
--- a/doc/gnosis.info
+++ b/doc/gnosis.info
@@ -14,14 +14,17 @@ Gnosis User Manual
Gnosis (γνῶσις), pronounced "noh-sis", _meaning knowledge in Greek_, is
a spaced repetition system implementation for note taking and self
-testing. The objective of gnosis is to maximize memory retention by
-implementing reviewing of information at increasing intervals.
+testing. Notes are organized in a Question/Answer/Explanation format
+and reviewed at spaced intervals, determined by the success or failure
+to recall the answer.
- The intervals grow longer as you become more familiar with the
-information, which reinforces long-term retention and reduces the risk
-of forgetting
+ The goal of Gnosis is to enhance memory retention through active
+recall. To achieve optimal results, users review Gnosis notes by
+writing out the answers.
-This manual is written for Gnosis version 0.3.0, released on 2024-06-28.
+ Above all, Gnosis aspires to be a versatile instrument of learning.
+
+This manual is written for Gnosis version 0.3.1, released on 2024-07-15.
• Official manual: <https://thanosapollo.org/user-manual/gnosis>
• Git repositories:
@@ -126,18 +129,20 @@ with "missing" words. A fill-in-the-blanks question.
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}
+ {c1:Cyproheptadine::drug name} 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}}’
+ You can also format clozes like Anki if you so prefer; e.g
+‘{{c1::Cyproheptadine::drug name}}’
- • For each 'cX'-tag there will be created a cloze type note, the
- above example creates 2 cloze type notes.
+ • 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
+ • Each cX tag can have multiple clozes, but each cloze must be a
*UNIQUE* word (or a unique combination of words) in given note.
+ • You can use the keyword ‘::’ to indicate a hint.
+
You can remove the _guidance_ string by adjusting
‘gnosis-cloze-guidance’.
@@ -452,26 +457,26 @@ should be done.

Tag Table:
Node: Top250
-Node: Introduction1503
-Node: Adding notes2230
-Node: Note Types2599
-Node: Cloze2824
-Node: MC-Cloze3720
-Node: MCQ (Multiple Choice Question)4544
-Node: Basic Type5043
-Node: Double5346
-Node: y-or-n5612
-Node: Customization6014
-Node: Image size6199
-Node: Typos | String Comparison6485
-Node: Gnosis Algorithm7260
-Node: Initial Interval8296
-Node: Easiness Factor9086
-Node: Forgetting Factor10034
-Node: Editing notes10642
-Node: Sync between devices11034
-Node: Extending Gnosis12055
-Node: Creating Custom Note Types12510
+Node: Introduction1614
+Node: Adding notes2341
+Node: Note Types2710
+Node: Cloze2935
+Node: MC-Cloze3913
+Node: MCQ (Multiple Choice Question)4737
+Node: Basic Type5236
+Node: Double5539
+Node: y-or-n5805
+Node: Customization6207
+Node: Image size6392
+Node: Typos | String Comparison6678
+Node: Gnosis Algorithm7453
+Node: Initial Interval8489
+Node: Easiness Factor9279
+Node: Forgetting Factor10227
+Node: Editing notes10835
+Node: Sync between devices11227
+Node: Extending Gnosis12248
+Node: Creating Custom Note Types12703

End Tag Table
diff --git a/doc/gnosis.org b/doc/gnosis.org
index 0e0ccde..dc2e1f5 100644
--- a/doc/gnosis.org
+++ b/doc/gnosis.org
@@ -4,8 +4,8 @@
#+language: en
#+options: ':t toc:nil author:t email:t num:t
#+startup: content
-#+macro: stable-version 0.3.0
-#+macro: release-date 2024-06-28
+#+macro: stable-version 0.3.1
+#+macro: release-date 2024-07-15
#+macro: file @@texinfo:@file{@@$1@@texinfo:}@@
#+macro: space @@texinfo:@: @@
#+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@
@@ -22,14 +22,18 @@
#+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. The objective of gnosis is to maximize memory retention by
-implementing reviewing of information at increasing intervals.
+testing. Notes are organized in a Question/Answer/Explanation format
+and reviewed at spaced intervals, determined by the success or failure
+to recall the answer.
+
+The goal of Gnosis is to enhance memory retention through active
+recall. To achieve optimal results, users review Gnosis notes by
+writing out the answers.
-The intervals grow longer as you become more familiar with the
-information, which reinforces long-term retention and reduces the risk
-of forgetting
+Above all, Gnosis aspires to be a versatile instrument of learning.
#+texinfo: @noindent
This manual is written for Gnosis version {{{stable-version}}}, released on {{{release-date}}}.
@@ -75,17 +79,19 @@ 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}
+{c1:Cyproheptadine::drug name} 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}}~
+You can also format clozes like Anki if you so prefer; e.g ~{{c1::Cyproheptadine::drug name}}~
-+ For each `cX`-tag there will be created a cloze type note, the above
++ 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
++ Each cX tag can have multiple clozes, but each cloze must be a
*UNIQUE* word (or a unique combination of words) in given note.
++ You can use the keyword =::= to indicate a hint.
+
You can remove the /guidance/ string by adjusting
=gnosis-cloze-guidance=.
@@ -117,7 +123,6 @@ The stem field (question) is separated by the options (choices) via
You can remove the /guidance/ string by adjusting
=gnosis-mcq-guidance=.
-
** Basic Type
Basic note type is a simple question/answer note, where the user first
diff --git a/doc/gnosis.texi b/doc/gnosis.texi
index f213740..b48163b 100644
--- a/doc/gnosis.texi
+++ b/doc/gnosis.texi
@@ -27,15 +27,18 @@
Gnosis (γνῶσις), pronounced ``noh-sis'', @emph{meaning knowledge in Greek},
is a spaced repetition system implementation for note taking and self
-testing. The objective of gnosis is to maximize memory retention by
-implementing reviewing of information at increasing intervals.
+testing. Notes are organized in a Question/Answer/Explanation format
+and reviewed at spaced intervals, determined by the success or failure
+to recall the answer.
-The intervals grow longer as you become more familiar with the
-information, which reinforces long-term retention and reduces the risk
-of forgetting
+The goal of Gnosis is to enhance memory retention through active
+recall. To achieve optimal results, users review Gnosis notes by
+writing out the answers.
+
+Above all, Gnosis aspires to be a versatile instrument of learning.
@noindent
-This manual is written for Gnosis version 0.3.0, released on 2024-06-28.
+This manual is written for Gnosis version 0.3.1, released on 2024-07-15.
@itemize
@item
@@ -139,20 +142,23 @@ 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@}
+@{c1:Cyproheptadine::drug name@} 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@}@}}
+You can also format clozes like Anki if you so prefer; e.g @code{@{@{c1::Cyproheptadine::drug name@}@}}
@itemize
@item
-For each `cX`-tag there will be created a cloze type note, the above
+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
+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.
+
+@item
+You can use the keyword @samp{::} to indicate a hint.
@end itemize
You can remove the @emph{guidance} string by adjusting
diff --git a/gnosis-test.el b/gnosis-test.el
index 24dc4bc..46edcf1 100644
--- a/gnosis-test.el
+++ b/gnosis-test.el
@@ -88,9 +88,9 @@ by the thoracodorsal nerve."
:tags (gnosis-test-random-items gnosis-test-tags 2))))
(when (y-or-n-p "Add single Cloze type?")
(dotimes (_ num)
+ ;; TODO: Update tests for include hints.
(gnosis-add-note--cloze :deck testing-deck
:note "this is a {c1:note}"
- :hint "note"
:tags (gnosis-test-random-items gnosis-test-tags 2)
:images (cons gnosis-test-image gnosis-test-image)
:extra "extra")))
diff --git a/gnosis.el b/gnosis.el
index 95364a9..44e3097 100644
--- a/gnosis.el
+++ b/gnosis.el
@@ -5,7 +5,7 @@
;; Author: Thanos Apollo <[email protected]>
;; Keywords: extensions
;; URL: https://thanosapollo.org/projects/gnosis
-;; Version: 0.3.0
+;; Version: 0.3.1
;; Package-Requires: ((emacs "27.2") (emacsql "20240124") (compat "29.1.4.2"))
@@ -38,6 +38,7 @@
;;; Code:
(require 'cl-lib)
+(require 'subr-x)
(require 'vc)
(require 'emacsql-sqlite)
@@ -57,7 +58,7 @@
:type 'directory
:group 'gnosis)
-(defcustom gnosis-cloze-string "__"
+(defcustom gnosis-cloze-string "[...]"
"Gnosis string to represent a cloze."
:type 'string
:group 'gnosis)
@@ -230,7 +231,7 @@ Seperate the question/stem from options."
:group 'gnosis-face)
(defface gnosis-face-cloze
- '((t :inherit cursor))
+ '((t :inherit (ffap italic)))
"Face for clozes."
:group 'gnosis-face)
@@ -320,12 +321,6 @@ History is disabled."
(let ((history-add-new-input nil))
(funcall gnosis-completing-read-function prompt (gnosis-shuffle seq))))
-(defun gnosis-replace-item-at-index (index new-item list)
- "Replace item at INDEX in LIST with NEW-ITEM."
- (cl-loop for i from 0 for item in list
- if (= i index) collect new-item
- else collect item))
-
(defun gnosis-insert-separator ()
"Insert a dashed line spanning the entire width of the buffer."
(interactive)
@@ -449,16 +444,82 @@ Refer to =gnosis-db-schema-extras' for informations on images stored."
do (insert (format "\n%s. %s" option-num option))
(setf option-num (1+ option-num)))))
-(cl-defun gnosis-display-cloze-sentence (sentence clozes)
- "Display cloze sentence for SENTENCE with CLOZES.
+;; FIXME: Adjust for multiple identical clozes
+(defun gnosis-display-cloze-sentence (sentence clozes hints success &optional failure)
+ "Display SENTENCE with CLOZES and HINTS.
+
+SUCCESS represents the number of correctly answered clozes.
+
+If FAILURE is t, it reveals all clozes that have not been answered yet
+with `gnosis-face-cloze-unanswered', only the current cloze will be
+revealed with `gnosis-face-false' and the ones before with
+`gnosis-face-correct'."
+ (cl-assert (listp clozes) "Clozes must be a list.")
+ (cl-assert (numberp success) "Success must be an integer.")
+ (cl-assert (or (not failure) (booleanp failure)) "Failure must be a boolean if provided.")
+
+ ;; Ensure hints is a list of the correct length. This also fixes
+ ;; older versions of cloze notes.
+ (setq hints (if (stringp hints)
+ (cons hints (make-list (1- (length clozes)) nil))
+ hints))
+ (cl-assert (listp hints) "Hints must be a list or a string.")
+
+ ;; Ensure hints list is the same length as clozes
+ (setq hints (append hints (make-list (- (length clozes) (length hints)) nil)))
+
+ (let ((result sentence)
+ (idx 0))
+ ;; Process each cloze
+ (cl-loop for cloze in clozes
+ do (let* ((hint (nth idx hints))
+ (display-cloze (cond
+ ((< idx success) cloze)
+ (failure cloze)
+ ((and hint (not (string-empty-p hint))) (format "[%s]" hint))
+ (t gnosis-cloze-string)))
+ (face (cond
+ ((< idx success) 'gnosis-face-correct)
+ ((and failure (= idx success)) 'gnosis-face-false)
+ ((and failure (> idx success)) 'gnosis-face-cloze-unanswered)
+ (t 'gnosis-face-cloze))))
+ ;; Replace only the first occurrence of each cloze in the sentence
+ (setq result (replace-regexp-in-string (concat "\\(" (regexp-quote cloze) "\\)")
+ (propertize display-cloze 'face face)
+ result
+ nil nil 1))
+ (setq idx (1+ idx))))
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (insert "\n" (gnosis-center-string (string-trim result)))
+ (gnosis-apply-syntax-overlay)
+ (gnosis-insert-separator))))
-If FILL-PARAGRAPH-P, insert using `fill-paragraph'"
- (erase-buffer)
- (let ((cloze-sentence
- (gnosis-cloze-replace-words sentence clozes (propertize gnosis-cloze-string 'face 'gnosis-face-cloze))))
- (insert "\n" (gnosis-center-string cloze-sentence))
- (gnosis-insert-separator)
- (gnosis-apply-syntax-overlay)))
+;; TODO: Reconsider using smaller functions for display cloze notes.
+
+;; (defun gnosis-add-clozes (sentence clozes &optional cloze-string)
+;; "Replace CLOZES in SENTENCE with CLOZE-STRING."
+;; (let ((cloze-string (or cloze-string gnosis-cloze-string)))
+;; (with-temp-buffer
+;; (insert sentence)
+;; (goto-char (point-min))
+;; (dolist (cloze clozes)
+;; (when (search-forward cloze nil t)
+;; (replace-match (propertize cloze-string 'face 'gnosis-face-cloze) nil t)))
+;; (buffer-string))))
+
+;; (defun gnosis-replace-clozes-with-hints (sentence hints &optional cloze-string)
+;; "Replace CLOZE-STRING in SENTENCE with HINTS."
+;; (let ((cloze-string (or cloze-string gnosis-cloze-string))
+;; (count 0))
+;; (with-temp-buffer
+;; (insert sentence)
+;; (goto-char (point-min))
+;; (while (search-forward cloze-string nil t)
+;; (when (and (nth count hints) (search-backward cloze-string nil t))
+;; (replace-match (propertize (format "[%s]" (nth count hints)) 'face 'gnosis-face-cloze)))
+;; (setq count (1+ count)))
+;; (buffer-string))))
(defun gnosis-display-basic-answer (answer success user-input)
"Display ANSWER.
@@ -501,18 +562,6 @@ SUCCESS is t when user-input is correct, else nil"
(insert (gnosis-center-string (propertize hint 'face 'gnosis-face-hint))))
(gnosis-insert-separator))))
-(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."
- (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)))
- (gnosis-center-current-line))
-
(cl-defun gnosis-display-cloze-user-answer (user-input &optional (false t))
"Display USER-INPUT answer for cloze note upon failed review.
@@ -605,13 +654,14 @@ Set SPLIT to t to split all input given."
(defun gnosis-add-deck (name)
"Create deck with NAME."
(interactive (list (read-string "Deck Name: ")))
- (when gnosis-testing
- (unless (y-or-n-p "You are using a testing environment! Continue?")
- (error "Aborted")))
- (if (gnosis-get 'name 'decks `(= name ,name))
- (error "Deck `%s' already exists" name)
- (gnosis--insert-into 'decks `([nil ,name nil nil nil nil nil]))
- (message "Created deck '%s'" name)))
+ (when gnosis-testing
+ (unless (y-or-n-p "You are using a testing environment! Continue?")
+ (error "Aborted")))
+ (if (gnosis-get 'name 'decks `(= name ,name))
+ (error "Deck `%s' already exists" name)
+ (let ((deck-id (gnosis-generate-id 5 t)))
+ (gnosis--insert-into 'decks `([,deck-id ,name nil nil nil nil nil]))
+ (message "Created deck '%s'" name))))
(defun gnosis--get-deck-name (&optional id)
"Get deck name for ID, or prompt for deck name when ID is nil."
@@ -689,15 +739,19 @@ When called with a prefix, unsuspends all notes for tag."
("Tag" (gnosis-suspend-tag))
(_ (message "Not ready yet.")))))
-(defun gnosis-generate-id (&optional length)
- "Generate a unique note ID.
+(defun gnosis-generate-id (&optional length deck-p)
+ "Generate a unique gnosis ID.
+
+Default to generating a note id, when DECK-P is t generates a deck id.
LENGTH: length of id, default to a random number between 10-15."
(let* ((length (or length (+ (random 5) 10)))
(max-val (expt 10 length))
(min-val (expt 10 (1- length)))
- (id (+ (random (- max-val min-val)) min-val)))
- (if (member id (gnosis-select 'id 'notes '1=1 t))
+ (id (+ (random (- max-val min-val)) min-val))
+ (current-ids (if deck-p (gnosis-select 'id 'decks '1=1 t)
+ (gnosis-select 'id 'notes '1=1 t))))
+ (if (member id current-ids)
(gnosis-generate-id length)
id)))
@@ -886,7 +940,7 @@ Refer to `gnosis-add-note--y-or-n' for more information about keyword values."
:tags (gnosis-prompt-tags--split gnosis-previous-note-tags)))
-(cl-defun gnosis-add-note--cloze (&key deck note hint tags (suspend 0) extra (images nil))
+(cl-defun gnosis-add-note--cloze (&key deck note tags (suspend 0) extra (images nil))
"Add cloze type note.
DECK: Deck name for note.
@@ -924,9 +978,12 @@ TAGS: Tags used to organize notes
SUSPEND: When t, note will be ignored.
EXTRA: Extra information displayed after user-input."
- (let ((notags-note (gnosis-cloze-remove-tags note))
- (clozes (gnosis-cloze-extract-answers note)))
+ (let* ((notags-note (gnosis-cloze-remove-tags note))
+ (cloze-contents (gnosis-cloze-extract-contents note))
+ (clozes (gnosis-cloze-extract-answers cloze-contents))
+ (hints (gnosis-cloze-extract-hints cloze-contents)))
(cl-loop for cloze in clozes
+ for hint in hints
do (gnosis-add-note-fields deck "cloze" notags-note hint cloze extra tags suspend
(car images) (cdr images)))))
@@ -960,7 +1017,6 @@ See `gnosis-add-note--cloze' for more reference."
(gnosis-add-note--cloze :deck deck
:note (gnosis-read-string-from-buffer (or (car gnosis-cloze-guidance) "")
(or (cdr gnosis-cloze-guidance) ""))
- :hint (gnosis-hint-prompt gnosis-previous-note-hint)
:extra (gnosis-read-string-from-buffer "Extra" "")
:images (gnosis-select-images)
:tags (gnosis-prompt-tags--split gnosis-previous-note-tags)))
@@ -1053,34 +1109,21 @@ TYPE: Type of gnosis note, must be one of `gnosis-note-types'"
(gnosis-completing-read "Answer: " choices)))
(defun gnosis-cloze-remove-tags (string)
- "Replace cx-tags in STRING.
+ "Replace cloze tags and hints in STRING.
-Works both with {} and {{}} to make easier to import anki notes."
- (let* ((regex "{\\{1,2\\}c\\([0-9]+\\)::?\\(.*?\\)}\\{1,2\\}")
- (result (replace-regexp-in-string regex "\\2" string)))
+Works with both single (:), double colons (::), single braces ({}) and
+double braces ({{}})."
+ (let* ((regex "{\\{1,2\\}c[0-9]+:\\{1,2\\}\\([^:}]*\\).*?\\(}\\|::}\\)\\{1,2\\}")
+ (result (replace-regexp-in-string regex "\\1" string)))
result))
-(defun gnosis-cloze-replace-words (string words new)
- "In STRING replace only the first occurrence of each word in WORDS with NEW."
- (cl-assert (listp words))
- (cl-loop for word in words
- do (if (string-match (concat "\\b" word "\\b") string)
- (setq string (replace-match new t t string))
- ;; This error will be produced when user has edited a
- ;; note to an invalid cloze.
- (error "`%s' is an invalid cloze for question: `%s'"
- word string)))
- string)
-
-(defun gnosis-cloze-extract-answers (str)
- "Extract cloze answers for STR.
+(defun gnosis-cloze-extract-contents (str)
+ "Extract cloze contents for STR.
-Return a list of cloze answers for STR, organized by cX-tag.
+Return a list of cloze tag contents for STR, organized by cX-tag.
Valid cloze formats include:
\"This is an {c1:example}\"
-\"This is an {c1::example}\"
-\"This is an {{c1:example}}\"
\"This is an {{c1::example}}\""
(let ((result-alist '())
(start 0))
@@ -1094,6 +1137,27 @@ Valid cloze formats include:
(mapcar (lambda (tag-group) (nreverse (cdr tag-group)))
(nreverse result-alist))))
+(defun gnosis-cloze-extract-answers (nested-lst)
+ "Extract cloze answers for string clozes inside the NESTED-LST.
+
+This function should be used in combination with `gnosis-cloze-extract-answers'."
+ (mapcar (lambda (lst)
+ (mapcar (lambda (str)
+ (replace-regexp-in-string "::\\(.*\\)" "" str))
+ lst))
+ nested-lst))
+
+(defun gnosis-cloze-extract-hints (nested-lst)
+ "Extract cloze hints for string clozes inside the NESTED-LST.
+
+This function should be used in combination with `gnosis-cloze-extract-answers'."
+ (mapcar (lambda (lst)
+ (mapcar (lambda (str)
+ (when (string-match "::\\(.*\\)" str)
+ (match-string 1 str)))
+ lst))
+ nested-lst))
+
(defun gnosis-mc-cloze-remove-separator (string &optional separator)
"Remove SEPARATOR and all followed words from STRING."
(let* ((separator (or separator gnosis-mc-cloze-separator))
@@ -1418,38 +1482,34 @@ If user-input is equal to CLOZE, return t."
(let ((user-input (read-string "Answer: ")))
(cons (gnosis-compare-strings user-input cloze) user-input)))
-(defun gnosis-review-cloze-reveal-unaswered (clozes)
- "Reveal CLOZES.
-
-Used to reveal all clozes left with `gnosis-face-cloze-unanswered' face."
- (cl-loop for cloze in clozes
- do (gnosis-display-cloze-reveal :replace cloze :face 'gnosis-face-cloze-unanswered)))
-
(defun gnosis-review-cloze (id)
"Review cloze type note for ID."
(let* ((main (gnosis-get 'main 'notes `(= id ,id)))
(clozes (gnosis-get 'answer 'notes `(= id ,id)))
- (num 1) ;; Number of clozes revealed
- (hint (gnosis-get 'options 'notes `(= id ,id)))
+ (num 0) ;; Number of clozes revealed
+ (hints (gnosis-get 'options 'notes `(= id ,id)))
(success nil))
- (gnosis-display-cloze-sentence main clozes)
- (gnosis-display-image id)
- (gnosis-display-hint hint)
+ ;; Initially display the sentence with no reveals
+ (message "reviewing %d" id)
+ ;; (when (or (stringp hints)
+ ;; (null hints))
+ ;; (setq hints nil))
+ ;; quick fix for old versions of gnosis cloze.
+ (message "Using deprecated cloze hints.")
+ (gnosis-display-cloze-sentence main clozes hints 0)
(cl-loop for cloze in clozes
do (let ((input (gnosis-review-cloze--input cloze)))
(if (equal (car input) t)
- ;; Reveal only one cloze
- (progn (gnosis-display-cloze-reveal :replace cloze)
- (setf num (1+ num)))
- ;; Reveal cloze for wrong input, with `gnosis-face-false'
- (gnosis-display-cloze-reveal :replace cloze :success nil)
+ ;; Correct answer -> reveal the current cloze
+ (progn (setq num (1+ num))
+ (gnosis-display-cloze-sentence main clozes hints num))
+ ;; Incorrect answer -> display current state with failure mode
+ (gnosis-display-cloze-sentence main clozes hints num t)
(gnosis-display-cloze-user-answer (cdr input))
- ;; Reveal all clozes left with `gnosis-face-cloze-unanswered' face
- (gnosis-review-cloze-reveal-unaswered (nthcdr num clozes))
- (setf success nil)
+ (setq success nil)
(cl-return)))
;; Update note after all clozes are revealed successfully
- finally (setf success t))
+ finally (setq success t))
(gnosis-display-extra id)
(gnosis-display-next-review id success)
success))
@@ -1461,12 +1521,13 @@ Used to reveal all clozes left with `gnosis-face-cloze-unanswered' face."
(cloze (list (gnosis-get 'answer 'notes `(= id ,id))))
(user-choice nil)
(success nil))
- (gnosis-display-cloze-sentence main cloze)
+ (gnosis-display-cloze-sentence main cloze nil 0 success)
(gnosis-display-image id)
(setf user-choice (gnosis-mcq-answer id)
success (string= user-choice (car cloze)))
- (gnosis-display-cloze-reveal :replace (car cloze)
- :success success)
+ (if success
+ (gnosis-display-cloze-sentence main cloze nil 1 nil)
+ (gnosis-display-cloze-sentence main cloze nil 0 t))
;; Display user answer only upon failure
(unless success
(gnosis-display-cloze-user-answer user-choice))
@@ -2075,12 +2136,11 @@ QUERY: String value,"
("Initial Interval" 20 t)
("Total Notes" 10 t)])
(tabulated-list-init-header)
- (let ((max-id (apply 'max (gnosis-select 'id 'decks '1=1 t))))
- (setq tabulated-list-entries
- (cl-loop for id from 1 to max-id
- for output = (gnosis-dashboard-output-deck id)
- when output
- collect (list (number-to-string id) (vconcat output)))))
+ (setq tabulated-list-entries
+ (cl-loop for id in (gnosis-select 'id 'decks '1=1 t)
+ for output = (gnosis-dashboard-output-deck id)
+ when output
+ collect (list (number-to-string id) (vconcat output))))
(local-set-key (kbd "e") #'gnosis-dashboard-edit-deck)
(local-set-key (kbd "a") #'(lambda () "Add deck & refresh" (interactive)
(gnosis-add-deck (read-string "Deck name: "))
@@ -2215,13 +2275,16 @@ If STRING-SECTION is nil, apply FACE to the entire STRING."
(sit-for 1.5)
(gnosis-animate-string "--A place to store & test your knowledge--" 4 nil nil 'italic)
(sit-for 1)
- (gnosis-animate-string "The objective of gnosis is to maximize memory retention." 6 nil
+ (gnosis-animate-string "The objective of gnosis is to maximize memory retention, through repetition." 6 nil
"maximize memory retention" 'underline)
(sit-for 1)
- (gnosis-animate-string "Consistency is key; be sure to do your daily reviews!" 8 nil "Consistency is key" 'bold)
+ (gnosis-animate-string "Remember, repetitio est mater memoriae" 8 nil
+ "repetitio est mater memoriae" 'bold-italic)
+ (sit-for 0.5)
+ (gnosis-animate-string "-- repetition is the mother of memory --" 9 nil
+ "repetition is the mother of memory" 'italic)
(sit-for 1)
- (gnosis-animate-string "Create meaningful notes; Gnosis offers a plethora of note types --try them!"
- 9 nil "Create Meaningful Notes" 'bold)
+ (gnosis-animate-string "Consistency is key; be sure to do your daily reviews!" 11 nil "Consistency is key" 'bold)
(sit-for 1)
(when (y-or-n-p "Try out demo gnosis review session?")
(gnosis-demo-create-deck)
@@ -2234,16 +2297,16 @@ If STRING-SECTION is nil, apply FACE to the entire STRING."
(if (not (cl-some #'(lambda (x) (member "demo" x)) (gnosis-select 'name 'decks)))
(progn (gnosis-add-deck deck-name)
(gnosis-add-note--basic :deck deck-name
- :question "What's the =key= that was mentioned in the /demo/ of gnosis?"
- :hint "__ is key!"
- :answer "Consistency"
- :extra "/Regular review/ at increasing intervals *reinforces memory retention*. Strengthening neural connections & making it easier to recall information long-term"
+ :question "Repetitio est mater memoriae"
+ :hint "Translate this Latin phrase to English."
+ :answer "Repetition is the mother of memory"
+ :extra "/Regular review/ at increasing intervals *reinforces* *memory* *retention*. Strengthening neural connections & making it easier to recall information long-term"
:tags note-tags)
(gnosis-add-note--mc-cloze :deck deck-name
- :question "Gnosis has a plethora of note types!"
- :options '("plethora" "limited selection")
- :answer "plethora"
- :extra "*Note types include*:\n\n=MCQ=: Multiple Choice Questions, to easily copy textbook review questions :)\n=Cloze=: Fill in the blank sentences\n=Basic=: Question-Answer-Explanation note\n=Double=: Creates 2 basic notes, second one is generated with the question & answer switched\n=MC-Cloze=: Multiple question cloze question, just like this current note\n=y-or-n=: Y or N questions"
+ :question "Consistency is _key_ to using gnosis effectively."
+ :options '("Consistency" "Procrastination" "Incosistency")
+ :answer "Consistency"
+ :extra "Avoid monotony, try to engage with the material actively, and stay _consistent_!"
:tags note-tags)
(gnosis-add-note--mcq :deck deck-name
:question "Which one is the capital of Greece?"
@@ -2252,8 +2315,7 @@ If STRING-SECTION is nil, apply FACE to the entire STRING."
:extra "Athens (Αθήνα) is the largest city of Greece & one of the world's oldest cities, with it's recorded history spanning over 3,500 years."
:tags note-tags)
(gnosis-add-note--cloze :deck deck-name
- :note "GNU Emacs is an extensible editor created by {c1:Richard} {c1:Stallman} in {c2:1984}"
- :hint ""
+ :note "GNU Emacs is an extensible editor created by {{c1::Richard}} {{c1::Stallman}} in {{c2::1984::year}}"
:tags note-tags
:extra "Emacs was originally implemented in 1976 on the MIT AI Lab's Incompatible Timesharing System (ITS), as a collection of TECO macros. The name “Emacs” was originally chosen as an abbreviation of “Editor MACroS”. =This version of Emacs=, GNU Emacs, was originally *written in 1984*")
(gnosis-add-note--y-or-n :deck deck-name