commit 4094cc228cc3a9f3e79e6eaae47808050abb01a3
parent 9cb390c90fec53e5855beba5db0fa60dda91a86c
Author: Yuval Langer <yuvallangerontheroad@gmail.com>
Date: Fri, 6 Oct 2023 00:16:16 +0300
Add some docstrings. Also `cl-loop`ify my loops.
Diffstat:
2 files changed, 117 insertions(+), 104 deletions(-)
diff --git a/.dir-locals.el b/.dir-locals.el
@@ -0,0 +1,2 @@
+((emacs-lisp-mode
+ (indent-tabs-mode nil
diff --git a/super-duper-yes-or-no.el b/super-duper-yes-or-no.el
@@ -57,13 +57,16 @@
(* 0 0)))
(defun sd--randint (minimum maximum)
- "Returns an integer between MINIMUM (inclusive) and MAXIMUM (exclusive)."
+ "Return an integer between MINIMUM (inclusive) and MAXIMUM (exclusive)."
(+ minimum
(random (- maximum
minimum))))
(defun sd--make-random-input-string (wanted-number-of-words)
+ "Make a list of words, WANTED-NUMBER-OF-WORDS long.
+
+Used in the `super-duper-yes-or-no-yes-or-no-words-p' function."
(let ((words ())
(wordlist-size (seq-length sd-words)))
(while (not (= (seq-length words)
@@ -76,6 +79,9 @@
words))
(defun sd--make-random-yes-or-no-input-pair (number-of-words)
+ "Make two different word lists, each NUMBER-OF-WORDS long.
+
+Used in super-duper-yes-or-no-words-p function."
(let ((yes-input (sd--make-random-input-string number-of-words)))
(named-let loop
((no-input (sd--make-random-input-string number-of-words)))
@@ -87,6 +93,15 @@
no-input))))))
(defun sd--list-intersperse (input-list intersperser)
+ "Return INPUT-LIST interspersed with INTERSPERSER.
+
+Example:
+
+\(sd--list-intersperse '(a b c) 'd)
+
+Will result with:
+
+'(a d b d c)"
(cond
((null input-list)
'())
@@ -98,7 +113,10 @@
(sd--list-intersperse (cdr input-list)
intersperser))))))
-(defun sd-yes-or-no-p (prompt)
+(defun sd-yes-or-no-words-p (prompt)
+ "Ask user a yes or no question.
+
+Display in minibuffer PROMPT followed by two sequences of words, one for yes and the other for no."
(let* ((wanted-yes-or-no (sd--make-random-yes-or-no-input-pair
sd-number-of-words))
(wanted-yes (car wanted-yes-or-no))
@@ -140,6 +158,15 @@
(upcase our-char))))
(defun sd--randomly-toggle-string-case (input-string number-of-chars-to-toggle)
+ "Toggle a number of chars' case in a string.
+
+A NUMBER-OF-CHARS-TO-TOGGLE chars will be selected at random from
+INPUT-STRING. Then function returns INPUT-STRING, with the
+selected chars' case toggled.
+
+NUMBERS-OF-CHARS-TO-TOGGLE MUST be less or equal to the number of
+English ASCII chars in INPUT-STRING - other chars do not count in
+the toggle count AND they are not toggled."
(let* ((input-length (length input-string))
(our-positions (number-sequence 0 (1- input-length)))
(our-shuffled-positions nil))
@@ -174,70 +201,62 @@
input-char)))))
(defun sd--string-only-uppercase (input-string)
- (concat
- (cl-loop for input-char
- across input-string
- when (char-uppercase-p input-char)
- collect input-char)))
+ "Return INPUT-STRING with only the uppercase chars."
+ (cl-loop
+ for input-char
+ across input-string
+ when (char-uppercase-p input-char)
+ concat (char-to-string input-char)))
(defun sd-yes-or-no-toggle-case-p (prompt)
- (let* ((wanted-yes-prompt
- (sd--randomly-toggle-string-case
- sd-upper-case-phrase-for-yes
- sd-number-of-case-toggle-characters))
- (wanted-no-prompt
- (sd--randomly-toggle-string-case
- sd-upper-case-phrase-for-no
- sd-number-of-case-toggle-characters))
- (wanted-input-yes
- (sd--string-only-uppercase
- wanted-yes-prompt))
- (wanted-input-no
- (sd--string-only-uppercase
- wanted-no-prompt))
- )
- (while (equal wanted-input-yes
- wanted-input-no)
- (setq wanted-yes-prompt
- (sd--randomly-toggle-string-case
- sd-upper-case-phrase-for-yes
- sd-number-of-case-toggle-characters))
- (setq wanted-no-prompt
- (sd--randomly-toggle-string-case
- sd-upper-case-phrase-for-no
- sd-number-of-case-toggle-characters))
- (setq wanted-input-yes
- (sd--string-only-uppercase
- wanted-yes-prompt))
- (setq wanted-input-no
- (sd--string-only-uppercase
- wanted-no-prompt)))
- (let ((user-input
- (read-from-minibuffer
- (concat prompt
- wanted-yes-prompt
- "\n"
- wanted-no-prompt
- ":\n"))))
- (while (not (or (equal user-input
- wanted-input-yes)
- (equal user-input
- wanted-input-no)))
- (setq user-input
- (read-from-minibuffer
- (concat prompt
- wanted-yes-prompt
- "\n"
- wanted-no-prompt
- ":\n"))))
- (equal user-input
- wanted-input-yes))))
+ "Ask user a yes or no question, but expect the uppercase letters.
+
+Display in minibuffer PROMPT followed by two lines, one for yes
+and the other for no. Each of those two lines have a sequence of
+uppercase letters sprinkled inside. If you want to answer yes,
+write in sequence the uppercase letters of the first line, otherwise, the uppercase letters of the second."
+ (cl-loop
+ for wanted-yes-prompt =
+ (sd--randomly-toggle-string-case
+ sd-upper-case-phrase-for-yes
+ sd-number-of-case-toggle-characters)
+ for wanted-no-prompt =
+ (sd--randomly-toggle-string-case
+ sd-upper-case-phrase-for-no
+ sd-number-of-case-toggle-characters)
+ for wanted-input-yes =
+ (sd--string-only-uppercase
+ wanted-yes-prompt)
+ for wanted-input-no =
+ (sd--string-only-uppercase
+ wanted-no-prompt)
+ while (equal wanted-input-yes
+ wanted-input-no)
+ finally return
+ (cl-loop
+ for user-input =
+ (read-from-minibuffer
+ (concat prompt
+ wanted-yes-prompt
+ "\n"
+ wanted-no-prompt
+ ":\n"))
+ until (or (equal user-input
+ wanted-input-yes)
+ (equal user-input
+ wanted-input-no))
+ finally return
+ (equal user-input
+ wanted-input-yes))))
(defun sd--make-arithmetic-problem-number ()
+ "Return a random integer number between the two variables.
+`sd-arithmetic-problem-minimum' and `sd-arithmetic-problem-maximum'."
(sd--randint sd-arithmetic-problem-minimum
(1+ sd-arithmetic-problem-maximum)))
(defun sd--make-arithmetic-problem-arguments (argument-list)
+ "Return ARGUMENT-LIST in an arithmetic problem with actual integer values."
(cond
((null argument-list)
'())
@@ -251,58 +270,50 @@
(cdr argument-list))))))
(defun sd--make-arithmetic-problem (arithmetic-expression-template)
+ "Make an arithmetic problem using an ARITHMETIC-EXPRESSION-TEMPLATE."
(cond
((null arithmetic-expression-template) '())
(t (cons (car arithmetic-expression-template)
(sd--make-arithmetic-problem-arguments (cdr arithmetic-expression-template))))))
(defun sd--yes-or-no-arithmetic-problem-p (prompt)
- (let* ((wanted-yes-prompt
- (sd--make-arithmetic-problem
- sd--arithmetic-problem-template))
- (wanted-no-prompt
- (sd--make-arithmetic-problem
- sd--arithmetic-problem-template))
- (wanted-input-yes
- (eval wanted-yes-prompt))
- (wanted-input-no
- (eval wanted-no-prompt)))
- (while (= wanted-input-yes
- wanted-input-no)
- (setq wanted-yes-prompt
- (sd--make-arithmetic-problem
- sd--arithmetic-problem-template))
- (setq wanted-no-prompt
- (sd--make-arithmetic-problem
- sd--arithmetic-problem-template))
- (setq wanted-input-yes
- (eval wanted-yes-prompt))
- (setq wanted-input-no
- (eval wanted-no-prompt)))
- (let ((user-input
- (string-to-number
- (read-from-minibuffer
- (concat prompt
- "Please answer "
- (format "%S" wanted-yes-prompt)
- " for \"yes\" and "
- (format "%S" wanted-no-prompt)
- " for \"no\": ")))))
- (while (not (or (= user-input
- wanted-input-yes)
- (= user-input
- wanted-input-no)))
- (setq user-input
- (string-to-number
- (read-from-minibuffer
- (concat prompt
- "Please answer "
- (format "%S" wanted-yes-prompt)
- " for \"yes\" and "
- (format "%S" wanted-no-prompt)
- " for \"no\": ")))))
- (= user-input
- wanted-input-yes))))
+ "Ask user a yes or no question, but as an answer to an arithmetic expression.
+
+Display in minibuffer PROMPT followed by two arithmetic
+expressions, one for yes and the other for no. If you want to
+answer yes, write the number that is the answer to the first
+problem, otherwise, the answer to the second problem."
+ (cl-loop
+ for wanted-yes-prompt =
+ (sd--make-arithmetic-problem
+ sd--arithmetic-problem-template)
+ for wanted-no-prompt =
+ (sd--make-arithmetic-problem
+ sd--arithmetic-problem-template)
+ for wanted-input-yes =
+ (eval wanted-yes-prompt)
+ for wanted-input-no =
+ (eval wanted-no-prompt)
+ while (= wanted-input-yes
+ wanted-input-no)
+ finally return
+ (cl-loop
+ for user-input =
+ (string-to-number
+ (read-from-minibuffer
+ (concat prompt
+ "Please answer "
+ (format "%S" wanted-yes-prompt)
+ " for \"yes\" and "
+ (format "%S" wanted-no-prompt)
+ " for \"no\": ")))
+ until (or (= user-input
+ wanted-input-yes)
+ (= user-input
+ wanted-input-no))
+ finally return
+ (= user-input
+ wanted-input-yes))))
;; Local Variables:
;; read-symbol-shorthands: (("sd-" . "super-duper-yes-or-no-"))