emacs-super-duper-yes-or-no

Replace the yes-or-no function with an even more demanding yes or no prompt, rather than with y-or-n.
Log | Files | Refs | LICENSE

commit 5424c666278844ff049a66310a045743a4402b87
parent b440b16626e7aaf3e971eccf2cbb55c09fff429a
Author: Yuval Langer <yuvallangerontheroad@gmail.com>
Date:   Tue,  3 Oct 2023 20:44:24 +0300

Add randomly toggled case string yes-or-no functionality.

Diffstat:
Msuper-duper-yes-or-no.el | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 129 insertions(+), 13 deletions(-)

diff --git a/super-duper-yes-or-no.el b/super-duper-yes-or-no.el @@ -38,12 +38,20 @@ "foo" "bar"]) +(defvar sd-upper-case-phrase-for-yes + "If you understand what you're doing, enter the capitalized letters here for \"yes\"") + +(defvar sd-upper-case-phrase-for-no + "If you understand what you're doing, enter the capitalized letters here for \"no\"") + +(defvar sd-number-of-case-toggle-characters 4) + (defun sd--randint (minimum maximum) - "Returns an integer between MINIMUM (inclusive) and MAXIMUM (exclusive)." + "Returns an integer between MINIMUM (inclusive) and MAXIMUM (exclusive)." - (+ minimum - (random (- maximum - minimum)))) + (+ minimum + (random (- maximum + minimum)))) (defun sd--make-random-input-string (wanted-number-of-words) (let ((words ()) @@ -58,15 +66,15 @@ words)) (defun sd--make-random-yes-or-no-input-pair (number-of-words) - (let ((result-label (gensym)) - (yes-input (sd--make-random-input-string number-of-words)) - (no-input (sd--make-random-input-string number-of-words))) - (while (equal yes-input - no-input) - (setq no-input - (sd--make-random-input-string number-of-words))) - (list yes-input - no-input))) + (let ((yes-input (sd--make-random-input-string number-of-words))) + (named-let loop + ((no-input (sd--make-random-input-string number-of-words))) + (cond + ((equal yes-input + no-input) + (loop (sd--make-random-input-string number-of-words))) + (t (list yes-input + no-input)))))) (defun sd--list-intersperse (input-list intersperser) (cond @@ -116,6 +124,114 @@ '()))))) result)) +(defun sd--toggle-char-case (our-char) + (cond + ((char-uppercase-p our-char) + (downcase our-char)) + (t + (upcase our-char)))) + +(defun sd--randomly-toggle-string-case (input-string number-of-chars-to-toggle) + (let* ((input-length (length input-string)) + (our-positions (number-sequence 0 (1- input-length))) + (our-shuffled-positions nil)) + (while (< (length our-shuffled-positions) + number-of-chars-to-toggle) + (let* ((wanted-position-index (random (length our-positions))) + (wanted-position (nth wanted-position-index + our-positions)) + (position-char (aref input-string + wanted-position))) + (when (or (and (>= position-char + (string-to-char "a")) + (<= position-char + (string-to-char "z"))) + (and (>= position-char + (string-to-char "A")) + (<= position-char + (string-to-char "Z")))) + (setq our-shuffled-positions + (cons wanted-position + our-shuffled-positions)) + (setq our-positions (delq wanted-position + our-positions))))) + + (concat + (cl-loop for input-char in (string-to-list input-string) + for input-string-position in (number-sequence 0 (1- input-length)) + collect (if (member + input-string-position + our-shuffled-positions) + (sd--toggle-char-case input-char) + 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))) + +(defun sd-yes-or-no-toggle-case-p (prompt) + (interactive) + + (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")))) + (cond + ((equal user-input + wanted-input-yes) + t) + ((equal user-input + wanted-input-no) + nil))))) + ;; Local Variables: ;; read-symbol-shorthands: (("sd-" . "super-duper-yes-or-no-")) ;; End: