55 | 55 |
(require 'org)
|
56 | 56 |
(require 'org-id)
|
57 | 57 |
(require 'savehist)
|
58 | |
|
59 | |
(eval-when-compile
|
60 | |
(require 'cl))
|
61 | |
|
62 | |
|
63 | 58 |
(require 'seq)
|
64 | 59 |
|
65 | 60 |
(defgroup org-drill nil
|
|
260 | 255 |
|
261 | 256 |
(defun org-drill--compute-cloze-keywords ()
|
262 | 257 |
(list (list (org-drill--compute-cloze-regexp)
|
263 | |
(copy-list '(1 'org-drill-visible-cloze-face nil))
|
264 | |
(copy-list '(2 'org-drill-visible-cloze-hint-face t))
|
265 | |
(copy-list '(3 'org-drill-visible-cloze-face nil))
|
|
258 |
(cl-copy-list '(1 'org-drill-visible-cloze-face nil))
|
|
259 |
(cl-copy-list '(2 'org-drill-visible-cloze-hint-face t))
|
|
260 |
(cl-copy-list '(3 'org-drill-visible-cloze-face nil))
|
266 | 261 |
)))
|
267 | 262 |
|
268 | 263 |
(defvar-local org-drill-cloze-regexp
|
|
682 | 677 |
(let ((idx (gensym)))
|
683 | 678 |
`(if (null ,place)
|
684 | 679 |
nil
|
685 | |
(let ((,idx (random* (length ,place))))
|
|
680 |
(let ((,idx (cl-random (length ,place))))
|
686 | 681 |
(prog1 (nth ,idx ,place)
|
687 | |
(setq ,place (append (subseq ,place 0 ,idx)
|
688 | |
(subseq ,place (1+ ,idx)))))))))
|
|
682 |
(setq ,place (append (cl-subseq ,place 0 ,idx)
|
|
683 |
(cl-subseq ,place (1+ ,idx)))))))))
|
689 | 684 |
|
690 | 685 |
|
691 | 686 |
(defmacro push-end (val place)
|
|
702 | 697 |
temp
|
703 | 698 |
(len (length list)))
|
704 | 699 |
(while (< i len)
|
705 | |
(setq j (+ i (random* (- len i))))
|
|
700 |
(setq j (+ i (cl-random (- len i))))
|
706 | 701 |
(setq temp (nth i list))
|
707 | 702 |
(setf (nth i list) (nth j list))
|
708 | 703 |
(setf (nth j list) temp)
|
|
750 | 745 |
skip)))
|
751 | 746 |
|
752 | 747 |
(defun org-drill-current-scope (scope)
|
753 | |
(case scope
|
|
748 |
(cl-case scope
|
754 | 749 |
(file nil)
|
755 | 750 |
(file-no-restriction 'file)
|
756 | 751 |
(directory
|
|
869 | 864 |
;; (or (not (eql 'skip org-drill-leech-method))
|
870 | 865 |
;; (not (org-drill-entry-leech-p)))
|
871 | 866 |
;; (or (null item-time) ; not scheduled
|
872 | |
;; (not (minusp ; scheduled for today/in past
|
|
867 |
;; (not (cl-minusp ; scheduled for today/in past
|
873 | 868 |
;; (- (time-to-days (current-time))
|
874 | 869 |
;; (time-to-days item-time))))))))))
|
875 | 870 |
|
|
924 | 919 |
(defun org-drill-entry-due-p ()
|
925 | 920 |
(let ((due (org-drill-entry-days-overdue)))
|
926 | 921 |
(and (not (null due))
|
927 | |
(not (minusp due)))))
|
|
922 |
(not (cl-minusp due)))))
|
928 | 923 |
|
929 | 924 |
|
930 | 925 |
(defun org-drill-entry-new-p ()
|
|
983 | 978 |
"Returns a random number between 0.5 and 1.5."
|
984 | 979 |
(let ((a 0.047)
|
985 | 980 |
(b 0.092)
|
986 | |
(p (- (random* 1.0) 0.5)))
|
|
981 |
(p (- (cl-random 1.0) 0.5)))
|
987 | 982 |
(cl-flet ((sign (n)
|
988 | 983 |
(cond ((zerop n) 0)
|
989 | |
((plusp n) 1)
|
|
984 |
((cl-plusp n) 1)
|
990 | 985 |
(t -1))))
|
991 | 986 |
(/ (+ 100 (* (* (/ -1 b) (log (- 1 (* (/ b a ) (abs p)))))
|
992 | 987 |
(sign p)))
|
|
995 | 990 |
(defun pseudonormal (mean variation)
|
996 | 991 |
"Random numbers in a pseudo-normal distribution with mean MEAN, range
|
997 | 992 |
MEAN-VARIATION to MEAN+VARIATION"
|
998 | |
(+ (random* variation)
|
999 | |
(random* variation)
|
|
993 |
(+ (cl-random variation)
|
|
994 |
(cl-random variation)
|
1000 | 995 |
(- variation)
|
1001 | 996 |
mean))
|
1002 | 997 |
|
|
1040 | 1035 |
(learn-str
|
1041 | 1036 |
(let ((learn-data (or (and learn-str
|
1042 | 1037 |
(read learn-str))
|
1043 | |
(copy-list initial-repetition-state))))
|
|
1038 |
(cp-copy-list initial-repetition-state))))
|
1044 | 1039 |
(list (nth 0 learn-data) ; last interval
|
1045 | 1040 |
(nth 1 learn-data) ; repetitions
|
1046 | 1041 |
(org-drill-entry-failure-count)
|
|
1098 | 1093 |
(/ (+ quality (* meanq total-repeats 1.0))
|
1099 | 1094 |
(1+ total-repeats))
|
1100 | 1095 |
quality))
|
1101 | |
(assert (> n 0))
|
1102 | |
(assert (and (>= quality 0) (<= quality 5)))
|
|
1096 |
(cl-assert (> n 0))
|
|
1097 |
(cl-assert (and (>= quality 0) (<= quality 5)))
|
1103 | 1098 |
(if (<= quality org-drill-failure-quality)
|
1104 | 1099 |
;; When an item is failed, its interval is reset to 0,
|
1105 | 1100 |
;; but its EF is unchanged
|
|
1113 | 1108 |
((= n 2)
|
1114 | 1109 |
(cond
|
1115 | 1110 |
(org-drill-add-random-noise-to-intervals-p
|
1116 | |
(case quality
|
|
1111 |
(cl-case quality
|
1117 | 1112 |
(5 6)
|
1118 | 1113 |
(4 4)
|
1119 | 1114 |
(3 3)
|
|
1178 | 1173 |
of-matrix &optional delta-days)
|
1179 | 1174 |
(if (zerop n) (setq n 1))
|
1180 | 1175 |
(if (null ef) (setq ef 2.5))
|
1181 | |
(assert (> n 0))
|
1182 | |
(assert (and (>= quality 0) (<= quality 5)))
|
|
1176 |
(cl-assert (> n 0))
|
|
1177 |
(cl-assert (and (>= quality 0) (<= quality 5)))
|
1183 | 1178 |
(unless of-matrix
|
1184 | 1179 |
(setq of-matrix org-drill-sm5-optimal-factor-matrix))
|
1185 | |
(setq of-matrix (cl-copy-tree of-matrix))
|
|
1180 |
(setq of-matrix (copy-tree of-matrix))
|
1186 | 1181 |
|
1187 | 1182 |
(setq meanq (if meanq
|
1188 | 1183 |
(/ (+ quality (* meanq total-repeats 1.0))
|
|
1195 | 1190 |
quality org-drill-learn-fraction))
|
1196 | 1191 |
(interval nil))
|
1197 | 1192 |
(when (and org-drill-adjust-intervals-for-early-and-late-repetitions-p
|
1198 | |
delta-days (minusp delta-days))
|
|
1193 |
delta-days (cl-minusp delta-days))
|
1199 | 1194 |
(setq new-of (org-drill-early-interval-factor
|
1200 | 1195 |
(get-optimal-factor-sm5 n ef of-matrix)
|
1201 | 1196 |
(inter-repetition-interval-sm5
|
|
1287 | 1282 |
- AVERAGE-QUALITY
|
1288 | 1283 |
- TOTAL-REPEATS.
|
1289 | 1284 |
See the documentation for `org-drill-get-item-data' for a description of these."
|
1290 | |
(assert (>= repeats 0))
|
1291 | |
(assert (and (>= quality 0) (<= quality 5)))
|
1292 | |
(assert (or (null meanq) (and (>= meanq 0) (<= meanq 5))))
|
|
1285 |
(cl-assert (>= repeats 0))
|
|
1286 |
(cl-assert (and (>= quality 0) (<= quality 5)))
|
|
1287 |
(cl-assert (or (null meanq) (and (>= meanq 0) (<= meanq 5))))
|
1293 | 1288 |
(let ((next-interval nil))
|
1294 | 1289 |
(setf meanq (if meanq
|
1295 | 1290 |
(/ (+ quality (* meanq totaln 1.0)) (1+ totaln))
|
1296 | 1291 |
quality))
|
1297 | 1292 |
(cond
|
1298 | 1293 |
((<= quality org-drill-failure-quality)
|
1299 | |
(incf failures)
|
|
1294 |
(cl-incf failures)
|
1300 | 1295 |
(setf repeats 0
|
1301 | 1296 |
next-interval -1))
|
1302 | 1297 |
((or (zerop repeats)
|
1303 | 1298 |
(zerop last-interval))
|
1304 | 1299 |
(setf next-interval (org-drill-simple8-first-interval failures))
|
1305 | |
(incf repeats)
|
1306 | |
(incf totaln))
|
|
1300 |
(cl-incf repeats)
|
|
1301 |
(cl-incf totaln))
|
1307 | 1302 |
(t
|
1308 | 1303 |
(let* ((use-n
|
1309 | 1304 |
(if (and
|
1310 | 1305 |
org-drill-adjust-intervals-for-early-and-late-repetitions-p
|
1311 | |
(numberp delta-days) (plusp delta-days)
|
1312 | |
(plusp last-interval))
|
|
1306 |
(numberp delta-days) (cl-plusp delta-days)
|
|
1307 |
(cl-plusp last-interval))
|
1313 | 1308 |
(+ repeats (min 1 (/ delta-days last-interval 1.0)))
|
1314 | 1309 |
repeats))
|
1315 | 1310 |
(factor (org-drill-simple8-interval-factor
|
1316 | 1311 |
(org-drill-simple8-quality->ease meanq) use-n))
|
1317 | 1312 |
(next-int (* last-interval factor)))
|
1318 | 1313 |
(when (and org-drill-adjust-intervals-for-early-and-late-repetitions-p
|
1319 | |
(numberp delta-days) (minusp delta-days))
|
|
1314 |
(numberp delta-days) (cl-minusp delta-days))
|
1320 | 1315 |
;; The item was reviewed earlier than scheduled.
|
1321 | 1316 |
(setf factor (org-drill-early-interval-factor
|
1322 | 1317 |
factor next-int (abs delta-days))
|
1323 | 1318 |
next-int (* last-interval factor)))
|
1324 | 1319 |
(setf next-interval next-int)
|
1325 | |
(incf repeats)
|
1326 | |
(incf totaln))))
|
|
1320 |
(cl-incf repeats)
|
|
1321 |
(cl-incf totaln))))
|
1327 | 1322 |
(list
|
1328 | 1323 |
(if (and org-drill-add-random-noise-to-intervals-p
|
1329 | |
(plusp next-interval))
|
|
1324 |
(cl-plusp next-interval))
|
1330 | 1325 |
(* next-interval (org-drill-random-dispersal-factor))
|
1331 | 1326 |
next-interval)
|
1332 | 1327 |
repeats
|
|
1355 | 1350 |
(weight (org-entry-get (point) "DRILL_CARD_WEIGHT")))
|
1356 | 1351 |
(if (stringp weight)
|
1357 | 1352 |
(setq weight (read weight)))
|
1358 | |
(destructuring-bind (last-interval repetitions failures
|
|
1353 |
(cl-destructuring-bind (last-interval repetitions failures
|
1359 | 1354 |
total-repeats meanq ease)
|
1360 | 1355 |
(org-drill-get-item-data)
|
1361 | |
(destructuring-bind (next-interval repetitions ease
|
|
1356 |
(cl-destructuring-bind (next-interval repetitions ease
|
1362 | 1357 |
failures meanq total-repeats
|
1363 | 1358 |
&optional new-ofmatrix)
|
1364 | |
(case org-drill-spaced-repetition-algorithm
|
|
1359 |
(cl-case org-drill-spaced-repetition-algorithm
|
1365 | 1360 |
(sm5 (determine-next-interval-sm5 last-interval repetitions
|
1366 | 1361 |
ease quality failures
|
1367 | 1362 |
meanq total-repeats ofmatrix))
|
|
1376 | 1371 |
(setq next-interval days-ahead))
|
1377 | 1372 |
|
1378 | 1373 |
(if (and (null days-ahead)
|
1379 | |
(numberp weight) (plusp weight)
|
1380 | |
(not (minusp next-interval)))
|
|
1374 |
(numberp weight) (cl-plusp weight)
|
|
1375 |
(not (cl-minusp next-interval)))
|
1381 | 1376 |
(setq next-interval
|
1382 | 1377 |
(max 1.0 (+ last-interval
|
1383 | 1378 |
(/ (- next-interval last-interval) weight)))))
|
|
1391 | 1386 |
(cond
|
1392 | 1387 |
((= 0 days-ahead)
|
1393 | 1388 |
(org-schedule '(4)))
|
1394 | |
((minusp days-ahead)
|
|
1389 |
((cl-minusp days-ahead)
|
1395 | 1390 |
(org-schedule nil (current-time)))
|
1396 | 1391 |
(t
|
1397 | 1392 |
(org-schedule nil (time-add (current-time)
|
|
1404 | 1399 |
that the current item would be scheduled, based on a recall quality
|
1405 | 1400 |
of QUALITY."
|
1406 | 1401 |
(let ((weight (org-entry-get (point) "DRILL_CARD_WEIGHT")))
|
1407 | |
(destructuring-bind (last-interval repetitions failures
|
|
1402 |
(cl-destructuring-bind (last-interval repetitions failures
|
1408 | 1403 |
total-repeats meanq ease)
|
1409 | 1404 |
(org-drill-get-item-data)
|
1410 | 1405 |
(if (stringp weight)
|
1411 | 1406 |
(setq weight (read weight)))
|
1412 | |
(destructuring-bind (next-interval repetitions ease
|
|
1407 |
(cl-destructuring-bind (next-interval repetitions ease
|
1413 | 1408 |
failures meanq total-repeats
|
1414 | 1409 |
&optional ofmatrix)
|
1415 | |
(case org-drill-spaced-repetition-algorithm
|
|
1410 |
(cl-case org-drill-spaced-repetition-algorithm
|
1416 | 1411 |
(sm5 (determine-next-interval-sm5 last-interval repetitions
|
1417 | 1412 |
ease quality failures
|
1418 | 1413 |
meanq total-repeats
|
|
1424 | 1419 |
quality failures meanq
|
1425 | 1420 |
total-repeats)))
|
1426 | 1421 |
(cond
|
1427 | |
((not (plusp next-interval))
|
|
1422 |
((not (cl-plusp next-interval))
|
1428 | 1423 |
0)
|
1429 | |
((and (numberp weight) (plusp weight))
|
|
1424 |
((and (numberp weight) (cl-plusp weight))
|
1430 | 1425 |
(+ last-interval
|
1431 | 1426 |
(max 1.0 (/ (- next-interval last-interval) weight))))
|
1432 | 1427 |
(t
|
|
1494 | 1489 |
((stringp input)
|
1495 | 1490 |
(setq ch (elt input 0)))
|
1496 | 1491 |
((and (vectorp input) (symbolp (elt input 0)))
|
1497 | |
(case (elt input 0)
|
|
1492 |
(cl-case (elt input 0)
|
1498 | 1493 |
(up (ignore-errors (forward-line -1)))
|
1499 | 1494 |
(down (ignore-errors (forward-line 1)))
|
1500 | 1495 |
(left (ignore-errors (backward-char)))
|
|
1503 | 1498 |
(next (ignore-errors (scroll-up))))) ; pgdn
|
1504 | 1499 |
((and (vectorp input) (listp (elt input 0))
|
1505 | 1500 |
(eventp (elt input 0)))
|
1506 | |
(case (car (elt input 0))
|
|
1501 |
(cl-case (car (elt input 0))
|
1507 | 1502 |
(wheel-up (ignore-errors (mwheel-scroll (elt input 0))))
|
1508 | 1503 |
(wheel-down (ignore-errors (mwheel-scroll (elt input 0)))))))
|
1509 | 1504 |
(if (eql ch org-drill--tags-key)
|
|
1595 | 1590 |
|
1596 | 1591 |
|
1597 | 1592 |
(defun org-drill--make-minibuffer-prompt (prompt)
|
1598 | |
(let ((status (first (org-drill-entry-status)))
|
|
1593 |
(let ((status (cl-first (org-drill-entry-status)))
|
1599 | 1594 |
(mature-entry-count (+ (length *org-drill-young-mature-entries*)
|
1600 | 1595 |
(length *org-drill-old-mature-entries*)
|
1601 | 1596 |
(length *org-drill-overdue-entries*))))
|
|
1606 | 1601 |
((eql status :failed) ?F)
|
1607 | 1602 |
(*org-drill-cram-mode* ?C)
|
1608 | 1603 |
(t
|
1609 | |
(case status
|
|
1604 |
(cl-case status
|
1610 | 1605 |
(:new ?N) (:young ?Y) (:old ?o) (:overdue ?!)
|
1611 | 1606 |
(t ??)))))
|
1612 | 1607 |
'face `(:foreground
|
1613 | |
,(case status
|
|
1608 |
,(cl-case status
|
1614 | 1609 |
(:new org-drill-new-count-color)
|
1615 | 1610 |
((:young :old) org-drill-mature-count-color)
|
1616 | 1611 |
((:overdue :failed) org-drill-failed-count-color)
|
|
1744 | 1739 |
(format-time-string "%M:%S " elapsed))
|
1745 | 1740 |
full-prompt)))
|
1746 | 1741 |
;; if we have done it this many times, we probably want to stop
|
1747 | |
(when (< 10 (incf org-drill-presentation-timer-calls))
|
|
1742 |
(when (< 10 (cl-incf org-drill-presentation-timer-calls))
|
1748 | 1743 |
(org-drill-presentation-timer-cancel)))
|
1749 | 1744 |
|
1750 | 1745 |
(define-derived-mode org-drill-response-mode nil "Org-Drill")
|
|
2027 | 2022 |
(p-max (save-excursion
|
2028 | 2023 |
(outline-next-heading)
|
2029 | 2024 |
(point))))
|
2030 | |
(assert (>= (- p-max p-min) (length replacements)))
|
|
2025 |
(cl-assert (>= (- p-max p-min) (length replacements)))
|
2031 | 2026 |
(dotimes (i (length replacements))
|
2032 | 2027 |
(setq ovl (make-overlay (+ p-min (* 2 i))
|
2033 | 2028 |
(if (= i (1- (length replacements)))
|
|
2157 | 2152 |
(let ((drill-sections (org-drill-hide-all-subheadings-except nil)))
|
2158 | 2153 |
(when drill-sections
|
2159 | 2154 |
(save-excursion
|
2160 | |
(goto-char (nth (random* (min 2 (length drill-sections)))
|
|
2155 |
(goto-char (nth (cl-random (min 2 (length drill-sections)))
|
2161 | 2156 |
drill-sections))
|
2162 | 2157 |
(org-show-subtree)))
|
2163 | 2158 |
(org-drill--show-latex-fragments)
|
|
2176 | 2171 |
(let ((drill-sections (org-drill-hide-all-subheadings-except nil)))
|
2177 | 2172 |
(when drill-sections
|
2178 | 2173 |
(save-excursion
|
2179 | |
(goto-char (nth (random* (length drill-sections)) drill-sections))
|
|
2174 |
(goto-char (nth (cl-random (length drill-sections)) drill-sections))
|
2180 | 2175 |
(org-show-subtree)))
|
2181 | 2176 |
(org-drill--show-latex-fragments)
|
2182 | 2177 |
(ignore-errors
|
|
2222 | 2217 |
org-bracket-link-regexp 1))))
|
2223 | 2218 |
(unless (or in-regexp?
|
2224 | 2219 |
(org-inside-LaTeX-fragment-p))
|
2225 | |
(incf match-count)))))
|
2226 | |
(if (minusp number-to-hide)
|
|
2220 |
(cl-incf match-count)))))
|
|
2221 |
(if (cl-minusp number-to-hide)
|
2227 | 2222 |
(setq number-to-hide (+ match-count number-to-hide)))
|
2228 | |
(when (plusp match-count)
|
|
2223 |
(when (cl-plusp match-count)
|
2229 | 2224 |
(let* ((positions (shuffle-list (loop for i from 1
|
2230 | 2225 |
to match-count
|
2231 | 2226 |
collect i)))
|
|
2240 | 2235 |
(if force-show-last
|
2241 | 2236 |
(setq positions (remove match-count positions)))
|
2242 | 2237 |
(setq match-nums
|
2243 | |
(subseq positions
|
|
2238 |
(cl-subseq positions
|
2244 | 2239 |
0 (min number-to-hide (length positions))))
|
2245 | 2240 |
;; (dolist (pos-to-hide match-nums)
|
2246 | 2241 |
(save-excursion
|
|
2251 | 2246 |
(or (org-pos-in-regexp (match-beginning 0)
|
2252 | 2247 |
org-bracket-link-regexp 1)
|
2253 | 2248 |
(org-inside-LaTeX-fragment-p)))
|
2254 | |
(incf cnt)
|
|
2249 |
(cl-incf cnt)
|
2255 | 2250 |
(if (memq cnt match-nums)
|
2256 | 2251 |
(org-drill-hide-matched-cloze-text)))))))
|
2257 | 2252 |
;; (loop
|
|
2292 | 2287 |
org-bracket-link-regexp 1))))
|
2293 | 2288 |
(unless (or in-regexp?
|
2294 | 2289 |
(org-inside-LaTeX-fragment-p))
|
2295 | |
(incf match-count)))))
|
2296 | |
(if (minusp to-hide)
|
|
2290 |
(cl-incf match-count)))))
|
|
2291 |
(if (cl-minusp to-hide)
|
2297 | 2292 |
(setq to-hide (+ 1 to-hide match-count)))
|
2298 | 2293 |
(cond
|
2299 | |
((or (not (plusp match-count))
|
|
2294 |
((or (not (cl-plusp match-count))
|
2300 | 2295 |
(> to-hide match-count))
|
2301 | 2296 |
nil)
|
2302 | 2297 |
(t
|
|
2311 | 2306 |
(or (org-pos-in-regexp (match-beginning 0)
|
2312 | 2307 |
org-bracket-link-regexp 1)
|
2313 | 2308 |
(org-inside-LaTeX-fragment-p)))
|
2314 | |
(incf cnt)
|
|
2309 |
(cl-incf cnt)
|
2315 | 2310 |
(if (= cnt to-hide)
|
2316 | 2311 |
(org-drill-hide-matched-cloze-text)))))))
|
2317 | 2312 |
(org-drill--show-latex-fragments)
|
|
2363 | 2358 |
;; Behave as hide1cloze
|
2364 | 2359 |
(org-drill-present-multicloze-hide1))
|
2365 | 2360 |
((not (and (integerp org-drill-cloze-text-weight)
|
2366 | |
(plusp org-drill-cloze-text-weight)))
|
|
2361 |
(cl-plusp org-drill-cloze-text-weight)))
|
2367 | 2362 |
(error "Illegal value for org-drill-cloze-text-weight: %S"
|
2368 | 2363 |
org-drill-cloze-text-weight))
|
2369 | 2364 |
((zerop (mod (1+ (org-drill-entry-total-repeats 0))
|
|
2388 | 2383 |
;; Behave as show1cloze
|
2389 | 2384 |
(org-drill-present-multicloze-show1))
|
2390 | 2385 |
((not (and (integerp org-drill-cloze-text-weight)
|
2391 | |
(plusp org-drill-cloze-text-weight)))
|
|
2386 |
(cl-plusp org-drill-cloze-text-weight)))
|
2392 | 2387 |
(error "Illegal value for org-drill-cloze-text-weight: %S"
|
2393 | 2388 |
org-drill-cloze-text-weight))
|
2394 | 2389 |
((zerop (mod (1+ (org-drill-entry-total-repeats 0))
|
|
2414 | 2409 |
;; Behave as show1cloze
|
2415 | 2410 |
(org-drill-present-multicloze-show1))
|
2416 | 2411 |
((not (and (integerp org-drill-cloze-text-weight)
|
2417 | |
(plusp org-drill-cloze-text-weight)))
|
|
2412 |
(cl-plusp org-drill-cloze-text-weight)))
|
2418 | 2413 |
(error "Illegal value for org-drill-cloze-text-weight: %S"
|
2419 | 2414 |
org-drill-cloze-text-weight))
|
2420 | 2415 |
((zerop (mod (1+ (org-drill-entry-total-repeats 0))
|
|
2513 | 2508 |
(let ((presentation-fn
|
2514 | 2509 |
(cdr (assoc card-type org-drill-card-type-alist))))
|
2515 | 2510 |
(if (listp presentation-fn)
|
2516 | |
(psetq answer-fn (or (second presentation-fn)
|
|
2511 |
(cl-psetq answer-fn (or (cl-second presentation-fn)
|
2517 | 2512 |
'org-drill-present-default-answer)
|
2518 | |
present-empty-cards (third presentation-fn)
|
2519 | |
presentation-fn (first presentation-fn)))
|
|
2513 |
present-empty-cards (cl-third presentation-fn)
|
|
2514 |
presentation-fn (cl-first presentation-fn)))
|
2520 | 2515 |
(let* ((tags (org-get-tags))
|
2521 | 2516 |
(rtn
|
2522 | 2517 |
(cond
|
|
2597 | 2592 |
|
2598 | 2593 |
|
2599 | 2594 |
(defun org-drill-pop-next-pending-entry ()
|
2600 | |
(block org-drill-pop-next-pending-entry
|
|
2595 |
(cl-block org-drill-pop-next-pending-entry
|
2601 | 2596 |
(let ((m nil))
|
2602 | 2597 |
(while (or (null m)
|
2603 | 2598 |
(not (org-drill-entry-p m)))
|
|
2629 | 2624 |
(not (org-drill-maximum-item-count-reached-p))
|
2630 | 2625 |
(not (org-drill-maximum-duration-reached-p)))
|
2631 | 2626 |
(cond
|
2632 | |
((< (random* (+ (length *org-drill-new-entries*)
|
|
2627 |
((< (cl-random (+ (length *org-drill-new-entries*)
|
2633 | 2628 |
(length *org-drill-old-mature-entries*)))
|
2634 | 2629 |
(length *org-drill-new-entries*))
|
2635 | 2630 |
(pop-random *org-drill-new-entries*))
|
|
2649 | 2644 |
'failed' and need to be presented again before the session ends.
|
2650 | 2645 |
|
2651 | 2646 |
RESUMING-P is true if we are resuming a suspended drill session."
|
2652 | |
(block org-drill-entries
|
|
2647 |
(cl-block org-drill-entries
|
2653 | 2648 |
(while (org-drill-entries-pending-p)
|
2654 | 2649 |
(let ((m (cond
|
2655 | 2650 |
((or (not resuming-p)
|
|
2704 | 2699 |
|
2705 | 2700 |
(defun org-drill-final-report ()
|
2706 | 2701 |
(let ((pass-percent
|
2707 | |
(round (* 100 (count-if (lambda (qual)
|
|
2702 |
(round (* 100 (cl-count-if (lambda (qual)
|
2708 | 2703 |
(> qual org-drill-failure-quality))
|
2709 | 2704 |
*org-drill-session-qualities*))
|
2710 | 2705 |
(max 1 (length *org-drill-session-qualities*))))
|
|
2725 | 2720 |
(length *org-drill-done-entries*)
|
2726 | 2721 |
(format-seconds "%h:%.2m:%.2s"
|
2727 | 2722 |
(- (float-time (current-time)) *org-drill-start-time*))
|
2728 | |
(round (* 100 (count 5 *org-drill-session-qualities*))
|
|
2723 |
(round (* 100 (cl-count 5 *org-drill-session-qualities*))
|
2729 | 2724 |
(max 1 (length *org-drill-session-qualities*)))
|
2730 | |
(round (* 100 (count 2 *org-drill-session-qualities*))
|
|
2725 |
(round (* 100 (cl-count 2 *org-drill-session-qualities*))
|
2731 | 2726 |
(max 1 (length *org-drill-session-qualities*)))
|
2732 | |
(round (* 100 (count 4 *org-drill-session-qualities*))
|
|
2727 |
(round (* 100 (cl-count 4 *org-drill-session-qualities*))
|
2733 | 2728 |
(max 1 (length *org-drill-session-qualities*)))
|
2734 | |
(round (* 100 (count 1 *org-drill-session-qualities*))
|
|
2729 |
(round (* 100 (cl-count 1 *org-drill-session-qualities*))
|
2735 | 2730 |
(max 1 (length *org-drill-session-qualities*)))
|
2736 | |
(round (* 100 (count 3 *org-drill-session-qualities*))
|
|
2731 |
(round (* 100 (cl-count 3 *org-drill-session-qualities*))
|
2737 | 2732 |
(max 1 (length *org-drill-session-qualities*)))
|
2738 | |
(round (* 100 (count 0 *org-drill-session-qualities*))
|
|
2733 |
(round (* 100 (cl-count 0 *org-drill-session-qualities*))
|
2739 | 2734 |
(max 1 (length *org-drill-session-qualities*)))
|
2740 | 2735 |
pass-percent
|
2741 | 2736 |
org-drill-failure-quality
|
|
2820 | 2815 |
(defun org-drill-order-overdue-entries (overdue-data)
|
2821 | 2816 |
(let* ((lapsed-days (if org-drill--lapse-very-overdue-entries-p
|
2822 | 2817 |
90 most-positive-fixnum))
|
2823 | |
(not-lapsed (remove-if (lambda (a) (> (or (second a) 0) lapsed-days))
|
|
2818 |
(not-lapsed (cl-remove-if (lambda (a) (> (or (cl-second a) 0) lapsed-days))
|
2824 | 2819 |
overdue-data))
|
2825 | |
(lapsed (remove-if-not (lambda (a) (> (or (second a) 0)
|
|
2820 |
(lapsed (cl-remove-if-not (lambda (a) (> (or (cl-second a) 0)
|
2826 | 2821 |
lapsed-days)) overdue-data)))
|
2827 | 2822 |
(setq *org-drill-overdue-entries*
|
2828 | 2823 |
(mapcar 'first
|
2829 | 2824 |
(append
|
2830 | 2825 |
(sort (shuffle-list not-lapsed)
|
2831 | |
(lambda (a b) (> (second a) (second b))))
|
|
2826 |
(lambda (a b) (> (cl-second a) (cl-second b))))
|
2832 | 2827 |
(sort lapsed
|
2833 | |
(lambda (a b) (> (third a) (third b)))))))))
|
|
2828 |
(lambda (a b) (> (cl-third a) (cl-third b)))))))))
|
2834 | 2829 |
|
2835 | 2830 |
|
2836 | 2831 |
(defun org-drill--entry-lapsed-p ()
|
|
2883 | 2878 |
(let* ((card-type (org-entry-get (point) "DRILL_CARD_TYPE" nil))
|
2884 | 2879 |
(dat (cdr (assoc card-type org-drill-card-type-alist))))
|
2885 | 2880 |
(or (null card-type)
|
2886 | |
(not (third dat)))))
|
|
2881 |
(not (cl-third dat)))))
|
2887 | 2882 |
;; body is empty, and this is not a card type where empty bodies are
|
2888 | 2883 |
;; meaningful, so skip it.
|
2889 | 2884 |
nil)
|
|
2891 | 2886 |
:unscheduled)
|
2892 | 2887 |
;; ((eql -1 due)
|
2893 | 2888 |
;; :tomorrow)
|
2894 | |
((minusp due) ; scheduled in the future
|
|
2889 |
((cl-minusp due) ; scheduled in the future
|
2895 | 2890 |
:future)
|
2896 | 2891 |
;; The rest of the stati all denote 'due' items ==========================
|
2897 | 2892 |
((<= (org-drill-entry-last-quality 9999)
|
|
2935 | 2930 |
(length *org-drill-young-mature-entries*)
|
2936 | 2931 |
(length *org-drill-old-mature-entries*)
|
2937 | 2932 |
(length *org-drill-failed-entries*))
|
2938 | |
(incf cnt))
|
|
2933 |
(cl-incf cnt))
|
2939 | 2934 |
(when (org-drill-entry-p)
|
2940 | 2935 |
(org-drill-id-get-create-with-warning)
|
2941 | |
(destructuring-bind (status due age)
|
|
2936 |
(cl-destructuring-bind (status due age)
|
2942 | 2937 |
(org-drill-entry-status)
|
2943 | |
(case status
|
|
2938 |
(cl-case status
|
2944 | 2939 |
(:unscheduled
|
2945 | |
(incf *org-drill-dormant-entry-count*))
|
|
2940 |
(cl-incf *org-drill-dormant-entry-count*))
|
2946 | 2941 |
;; (:tomorrow
|
2947 | |
;; (incf *org-drill-dormant-entry-count*)
|
2948 | |
;; (incf *org-drill-due-tomorrow-count*))
|
|
2942 |
;; (cl-incf *org-drill-dormant-entry-count*)
|
|
2943 |
;; (cl-incf *org-drill-due-tomorrow-count*))
|
2949 | 2944 |
(:future
|
2950 | |
(incf *org-drill-dormant-entry-count*)
|
|
2945 |
(cl-incf *org-drill-dormant-entry-count*)
|
2951 | 2946 |
(if (eq -1 due)
|
2952 | |
(incf *org-drill-due-tomorrow-count*)))
|
|
2947 |
(cl-incf *org-drill-due-tomorrow-count*)))
|
2953 | 2948 |
(:new
|
2954 | 2949 |
(push (point-marker) *org-drill-new-entries*))
|
2955 | 2950 |
(:failed
|
|
3012 | 3007 |
;; Check org version. Org 7.9.3f introduced a backwards-incompatible change
|
3013 | 3008 |
;; to the arguments accepted by `org-schedule'. At the time of writing there
|
3014 | 3009 |
;; are still lots of people using versions of org older than this.
|
3015 | |
(let ((majorv (first (mapcar 'string-to-number (split-string (org-release) "[.]")))))
|
|
3010 |
(let ((majorv (cl-first (mapcar 'string-to-number (split-string (org-release) "[.]")))))
|
3016 | 3011 |
(if (and (< majorv 8)
|
3017 | 3012 |
(not (string-match-p "universal prefix argument" (documentation 'org-schedule))))
|
3018 | 3013 |
(read-char-exclusive
|
|
3022 | 3017 |
(let ((end-pos nil)
|
3023 | 3018 |
(overdue-data nil)
|
3024 | 3019 |
(cnt 0))
|
3025 | |
(block org-drill
|
|
3020 |
(cl-block org-drill
|
3026 | 3021 |
(unless resume-p
|
3027 | 3022 |
(org-drill-free-markers t)
|
3028 | 3023 |
(setq *org-drill-current-item* nil
|
|
3039 | 3034 |
*org-drill-again-entries* nil)
|
3040 | 3035 |
(setq *org-drill-session-qualities* nil)
|
3041 | 3036 |
(setq *org-drill-start-time* (float-time (current-time))))
|
3042 | |
(setq *random-state* (make-random-state t)) ; reseed RNG
|
|
3037 |
(setq *random-state* (cl-make-random-state t)) ; reseed RNG
|
3043 | 3038 |
(unwind-protect
|
3044 | 3039 |
(save-excursion
|
3045 | 3040 |
(unless resume-p
|
|
3135 | 3130 |
(interactive)
|
3136 | 3131 |
(setq *org-drill-cram-mode* nil)
|
3137 | 3132 |
(cond
|
3138 | |
((plusp (org-drill-pending-entry-count))
|
|
3133 |
((cl-plusp (org-drill-pending-entry-count))
|
3139 | 3134 |
(org-drill-free-markers *org-drill-done-entries*)
|
3140 | 3135 |
(if (markerp *org-drill-current-item*)
|
3141 | 3136 |
(free-marker *org-drill-current-item*))
|
|
3155 | 3150 |
(cond
|
3156 | 3151 |
((org-drill-entries-pending-p)
|
3157 | 3152 |
(org-drill nil nil t))
|
3158 | |
((and (plusp (org-drill-pending-entry-count))
|
|
3153 |
((and (cl-plusp (org-drill-pending-entry-count))
|
3159 | 3154 |
;; Current drill session is finished, but there are still
|
3160 | 3155 |
;; more items which need to be reviewed.
|
3161 | 3156 |
(y-or-n-p (format
|
|
3209 | 3204 |
(setq-local org-drill-cloze-keywords (org-drill--compute-cloze-keywords))
|
3210 | 3205 |
(when org-drill-use-visible-cloze-face-p
|
3211 | 3206 |
(add-to-list 'org-font-lock-extra-keywords
|
3212 | |
(first org-drill-cloze-keywords))))
|
|
3207 |
(cl-first org-drill-cloze-keywords))))
|
3213 | 3208 |
|
3214 | 3209 |
|
3215 | 3210 |
;; Can't add to org-mode-hook, because local variables won't have been loaded
|
|
3242 | 3237 |
(defun org-drill-copy-entry-to-other-buffer (dest &optional path)
|
3243 | 3238 |
"Copy the subtree at point to the buffer DEST. The copy will receive
|
3244 | 3239 |
the tag 'imported'."
|
3245 | |
(block org-drill-copy-entry-to-other-buffer
|
|
3240 |
(cl-block org-drill-copy-entry-to-other-buffer
|
3246 | 3241 |
(save-excursion
|
3247 | 3242 |
(let ((src (current-buffer))
|
3248 | 3243 |
(m nil))
|
|
3335 | 3330 |
;; scheduling data, then go to the matching location in dest
|
3336 | 3331 |
;; and write the data.
|
3337 | 3332 |
(let ((marker (gethash id *org-drill-dest-id-table*)))
|
3338 | |
(destructuring-bind (last-interval repetitions failures
|
|
3333 |
(cl-destructuring-bind (last-interval repetitions failures
|
3339 | 3334 |
total-repeats meanq ease)
|
3340 | 3335 |
(org-drill-get-item-data)
|
3341 | 3336 |
(setq last-reviewed (org-entry-get (point) "DRILL_LAST_REVIEWED")
|
|
3434 | 3429 |
translation (car (read-from-string translation)))
|
3435 | 3430 |
(setq highlight-face
|
3436 | 3431 |
(list :foreground
|
3437 | |
(or (second (assoc-string tense org-drill-verb-tense-alist t))
|
|
3432 |
(or (cl-second (assoc-string tense org-drill-verb-tense-alist t))
|
3438 | 3433 |
"hotpink")
|
3439 | 3434 |
:background
|
3440 | 3435 |
(or
|
3441 | |
(second (assoc-string mood org-drill-verb-tense-alist t))
|
|
3436 |
(cl-second (assoc-string mood org-drill-verb-tense-alist t))
|
3442 | 3437 |
"black")))
|
3443 | 3438 |
(setq infinitive (propertize infinitive 'face highlight-face))
|
3444 | 3439 |
(setq translation (propertize translation 'face highlight-face))
|
|
3458 | 3453 |
(format "%s tense" tense))
|
3459 | 3454 |
(mood
|
3460 | 3455 |
(format "%s mood" mood)))))
|
3461 | |
(destructuring-bind (infinitive inf-hint translation tense mood)
|
|
3456 |
(cl-destructuring-bind (infinitive inf-hint translation tense mood)
|
3462 | 3457 |
(org-drill-get-verb-conjugation-info)
|
3463 | 3458 |
(org-drill-present-card-using-text
|
3464 | 3459 |
(cond
|
3465 | |
((zerop (random* 2))
|
|
3460 |
((zerop (cl-random 2))
|
3466 | 3461 |
(format "\nTranslate the verb\n\n%s\n\nand conjugate for the %s.\n\n"
|
3467 | 3462 |
infinitive (tense-and-mood-to-string tense mood)))
|
3468 | 3463 |
|
|
3478 | 3473 |
"Show the answer for a drill item whose card type is 'conjugate'.
|
3479 | 3474 |
RESCHEDULE-FN must be a function that calls `org-drill-reschedule' and
|
3480 | 3475 |
returns its return value."
|
3481 | |
(destructuring-bind (infinitive inf-hint translation tense mood)
|
|
3476 |
(cl-destructuring-bind (infinitive inf-hint translation tense mood)
|
3482 | 3477 |
(org-drill-get-verb-conjugation-info)
|
3483 | 3478 |
(with-replaced-entry-heading
|
3484 | 3479 |
(format "%s of %s ==> %s\n\n"
|
|
3533 | 3528 |
translation (car (read-from-string translation)))
|
3534 | 3529 |
(setq highlight-face
|
3535 | 3530 |
(list :foreground
|
3536 | |
(or (second (assoc-string noun-gender
|
|
3531 |
(or (cl-second (assoc-string noun-gender
|
3537 | 3532 |
org-drill-noun-gender-alist t))
|
3538 | 3533 |
"red")))
|
3539 | 3534 |
(setq noun (propertize noun 'face highlight-face))
|
|
3543 | 3538 |
|
3544 | 3539 |
(defun org-drill-present-noun-declension ()
|
3545 | 3540 |
"Present a drill entry whose card type is 'decline_noun'."
|
3546 | |
(destructuring-bind (noun noun-root noun-gender noun-hint translation)
|
|
3541 |
(cl-destructuring-bind (noun noun-root noun-gender noun-hint translation)
|
3547 | 3542 |
(org-drill-get-noun-info)
|
3548 | 3543 |
(let* ((props (org-entry-properties (point)))
|
3549 | 3544 |
(definite
|
|
3562 | 3557 |
(t nil))))
|
3563 | 3558 |
(org-drill-present-card-using-text
|
3564 | 3559 |
(cond
|
3565 | |
((zerop (random* 2))
|
|
3560 |
((zerop (cl-random 2))
|
3566 | 3561 |
(format "\nTranslate the noun\n\n%s (%s)\n\nand list its declensions%s.\n\n"
|
3567 | 3562 |
noun noun-gender
|
3568 | 3563 |
(if (or plural definite)
|
|
3582 | 3577 |
"Show the answer for a drill item whose card type is 'decline_noun'.
|
3583 | 3578 |
RESCHEDULE-FN must be a function that calls `org-drill-reschedule' and
|
3584 | 3579 |
returns its return value."
|
3585 | |
(destructuring-bind (noun noun-root noun-gender noun-hint translation)
|
|
3580 |
(cl-destructuring-bind (noun noun-root noun-gender noun-hint translation)
|
3586 | 3581 |
(org-drill-get-noun-info)
|
3587 | 3582 |
(with-replaced-entry-heading
|
3588 | 3583 |
(format "Declensions of %s (%s) ==> %s\n\n"
|
|
3618 | 3613 |
(psetf num-min num-max
|
3619 | 3614 |
num-max num-min))
|
3620 | 3615 |
(setq drilled-number
|
3621 | |
(+ num-min (random* (abs (1+ (- num-max num-min))))))
|
|
3616 |
(+ num-min (cl-random (abs (1+ (- num-max num-min))))))
|
3622 | 3617 |
(setq drilled-number-direction
|
3623 | |
(if (zerop (random* 2)) 'from-english 'to-english))
|
|
3618 |
(if (zerop (cl-random 2)) 'from-english 'to-english))
|
3624 | 3619 |
(cond
|
3625 | 3620 |
((eql 'to-english drilled-number-direction)
|
3626 | 3621 |
(org-drill-present-card-using-text
|
|
3673 | 3668 |
(with-hidden-comments
|
3674 | 3669 |
(with-hidden-cloze-hints
|
3675 | 3670 |
(with-hidden-cloze-text
|
3676 | |
(case (random* 6)
|
|
3671 |
(cl-case (cl-random 6)
|
3677 | 3672 |
(0
|
3678 | 3673 |
(org-drill-hide-all-subheadings-except '("Infinitive"))
|
3679 | 3674 |
(setq prompt
|
|
3780 | 3775 |
;; org-drill-again uses org-drill-pending-entry-count to decide
|
3781 | 3776 |
;; whether it needs to scan or not.
|
3782 | 3777 |
(let ((pending (org-drill-pending-entry-count)))
|
3783 | |
(unless (plusp pending)
|
|
3778 |
(unless (cl-plusp pending)
|
3784 | 3779 |
(let ((warned-about-id-creation nil)
|
3785 | 3780 |
(cnt 0)
|
3786 | 3781 |
(overdue-data nil)
|
|
3895 | 3890 |
(+ (length org-drill-leitner-unboxed-entries)
|
3896 | 3891 |
(length org-drill-leitner-boxed-entries))
|
3897 | 3892 |
;; This variable is dynamically scoped in!
|
3898 | |
(incf cnt))
|
|
3893 |
(cl-incf cnt))
|
3899 | 3894 |
(when (org-drill-entry-p)
|
3900 | 3895 |
(org-drill-id-get-create-with-warning)
|
3901 | 3896 |
(let ((leitner-box (org-entry-get (point) "DRILL_LEITNER_BOX" nil)))
|
|
3957 | 3952 |
((stringp input)
|
3958 | 3953 |
(setq ch (elt input 0)))
|
3959 | 3954 |
((and (vectorp input) (symbolp (elt input 0)))
|
3960 | |
(case (elt input 0)
|
|
3955 |
(cl-case (elt input 0)
|
3961 | 3956 |
(up (ignore-errors (forward-line -1)))
|
3962 | 3957 |
(down (ignore-errors (forward-line 1)))
|
3963 | 3958 |
(left (ignore-errors (backward-char)))
|
|
3966 | 3961 |
(next (ignore-errors (scroll-up))))) ; pgdn
|
3967 | 3962 |
((and (vectorp input) (listp (elt input 0))
|
3968 | 3963 |
(eventp (elt input 0)))
|
3969 | |
(case (car (elt input 0))
|
|
3964 |
(cl-case (car (elt input 0))
|
3970 | 3965 |
(wheel-up (ignore-errors (mwheel-scroll (elt input 0))))
|
3971 | 3966 |
(wheel-down (ignore-errors (mwheel-scroll (elt input 0)))))))
|
3972 | 3967 |
(if (eql ch org-drill--tags-key)
|
|
4010 | 4005 |
(org-toggle-tag "leitner" 'off)
|
4011 | 4006 |
(when org-drill-leitner-promote-to-drill-p
|
4012 | 4007 |
(org-toggle-tag "drill" 'on))
|
4013 | |
(incf org-drill-leitner-completed))
|
|
4008 |
(cl-incf org-drill-leitner-completed))
|
4014 | 4009 |
(org-set-property
|
4015 | 4010 |
"DRILL_LEITNER_BOX"
|
4016 | 4011 |
(format
|