diff options
| author | Glenn Morris | 2013-06-21 00:35:33 -0700 |
|---|---|---|
| committer | Glenn Morris | 2013-06-21 00:35:33 -0700 |
| commit | e7a526e3beb2ddadaad24ccd26d75fb55f7965bd (patch) | |
| tree | 1314a1e6270e066cf8956dbf1e35b1f9c71bd23e | |
| parent | 62efb35e42807972b8599e52c42e2c7302e25aa8 (diff) | |
| download | emacs-e7a526e3beb2ddadaad24ccd26d75fb55f7965bd.tar.gz emacs-e7a526e3beb2ddadaad24ccd26d75fb55f7965bd.zip | |
cookie1.el small cleanup
Make some funcs interactive, copy some functionality from yow.el.
* lisp/play/cookie1.el (cookie): New custom group.
(cookie-file): New option.
(cookie-check-file): New function.
(cookie): Make it interactive. Make start and end messages optional.
Interactively, display the result. Default to cookie-file.
(cookie-insert): Default to cookie-file.
(cookie-snarf): Make start and end messages optional.
Default to cookie-file. Use with-temp-buffer.
(cookie-read): Rename from read-cookie.
Make start and end messages optional. Default to cookie-file.
(cookie-shuffle-vector): Rename from shuffle-vector. Use dotimes.
(cookie-apropos, cookie-doctor): New functions, copied from yow.el
* lisp/obsolete/yow.el (read-zippyism): Use new name for read-cookie.
| -rw-r--r-- | lisp/ChangeLog | 16 | ||||
| -rw-r--r-- | lisp/obsolete/yow.el | 2 | ||||
| -rw-r--r-- | lisp/play/cookie1.el | 169 |
3 files changed, 145 insertions, 42 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 7c6a59c75f7..99072b43f61 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | 2013-06-21 Glenn Morris <rgm@gnu.org> | ||
| 2 | |||
| 3 | * play/cookie1.el (cookie): New custom group. | ||
| 4 | (cookie-file): New option. | ||
| 5 | (cookie-check-file): New function. | ||
| 6 | (cookie): Make it interactive. Make start and end messages optional. | ||
| 7 | Interactively, display the result. Default to cookie-file. | ||
| 8 | (cookie-insert): Default to cookie-file. | ||
| 9 | (cookie-snarf): Make start and end messages optional. | ||
| 10 | Default to cookie-file. Use with-temp-buffer. | ||
| 11 | (cookie-read): Rename from read-cookie. | ||
| 12 | Make start and end messages optional. Default to cookie-file. | ||
| 13 | (cookie-shuffle-vector): Rename from shuffle-vector. Use dotimes. | ||
| 14 | (cookie-apropos, cookie-doctor): New functions, copied from yow.el | ||
| 15 | * obsolete/yow.el (read-zippyism): Use new name for read-cookie. | ||
| 16 | |||
| 1 | 2013-06-21 Leo Liu <sdl.web@gmail.com> | 17 | 2013-06-21 Leo Liu <sdl.web@gmail.com> |
| 2 | 18 | ||
| 3 | * progmodes/octave.el (octave-mode): Backward compatibility fix. | 19 | * progmodes/octave.el (octave-mode): Backward compatibility fix. |
diff --git a/lisp/obsolete/yow.el b/lisp/obsolete/yow.el index 42bb0a0b354..abada670d6c 100644 --- a/lisp/obsolete/yow.el +++ b/lisp/obsolete/yow.el | |||
| @@ -60,7 +60,7 @@ | |||
| 60 | (defsubst read-zippyism (prompt &optional require-match) | 60 | (defsubst read-zippyism (prompt &optional require-match) |
| 61 | "Read a Zippyism from the minibuffer with completion, prompting with PROMPT. | 61 | "Read a Zippyism from the minibuffer with completion, prompting with PROMPT. |
| 62 | If optional second arg is non-nil, require input to match a completion." | 62 | If optional second arg is non-nil, require input to match a completion." |
| 63 | (read-cookie prompt yow-file yow-load-message yow-after-load-message | 63 | (cookie-read prompt yow-file yow-load-message yow-after-load-message |
| 64 | require-match)) | 64 | require-match)) |
| 65 | 65 | ||
| 66 | ;;;###autoload | 66 | ;;;###autoload |
diff --git a/lisp/play/cookie1.el b/lisp/play/cookie1.el index d060c31aebc..69cf4d538b2 100644 --- a/lisp/play/cookie1.el +++ b/lisp/play/cookie1.el | |||
| @@ -25,11 +25,10 @@ | |||
| 25 | ;;; Commentary: | 25 | ;;; Commentary: |
| 26 | 26 | ||
| 27 | ;; Support for random cookie fetches from phrase files, used for such | 27 | ;; Support for random cookie fetches from phrase files, used for such |
| 28 | ;; critical applications as emulating Zippy the Pinhead and confounding | 28 | ;; critical applications as confounding the NSA Trunk Trawler. |
| 29 | ;; the NSA Trunk Trawler. | ||
| 30 | ;; | 29 | ;; |
| 31 | ;; The two entry points are `cookie' and `cookie-insert'. The helper | 30 | ;; The two entry points are `cookie' and `cookie-insert'. The helper |
| 32 | ;; function `shuffle-vector' may be of interest to programmers. | 31 | ;; function `cookie-shuffle-vector' may be of interest to programmers. |
| 33 | ;; | 32 | ;; |
| 34 | ;; The code expects phrase files to be in one of two formats: | 33 | ;; The code expects phrase files to be in one of two formats: |
| 35 | ;; | 34 | ;; |
| @@ -49,32 +48,62 @@ | |||
| 49 | ;; This code derives from Steve Strassmann's 1987 spook.el package, but | 48 | ;; This code derives from Steve Strassmann's 1987 spook.el package, but |
| 50 | ;; has been generalized so that it supports multiple simultaneous | 49 | ;; has been generalized so that it supports multiple simultaneous |
| 51 | ;; cookie databases and fortune files. It is intended to be called | 50 | ;; cookie databases and fortune files. It is intended to be called |
| 52 | ;; from other packages such as yow.el and spook.el. | 51 | ;; from other packages such as spook.el. |
| 53 | 52 | ||
| 54 | ;;; Code: | 53 | ;;; Code: |
| 55 | 54 | ||
| 55 | (defgroup cookie nil | ||
| 56 | "Random cookies from phrase files." | ||
| 57 | :prefix "cookie-" | ||
| 58 | :group 'games) | ||
| 59 | |||
| 60 | (defcustom cookie-file nil | ||
| 61 | "Default phrase file for cookie functions." | ||
| 62 | :type '(choice (const nil) file) | ||
| 63 | :group 'cookie | ||
| 64 | :version "24.4") | ||
| 65 | |||
| 56 | (defconst cookie-delimiter "\n%%\n\\|\n%\n\\|\0" | 66 | (defconst cookie-delimiter "\n%%\n\\|\n%\n\\|\0" |
| 57 | "Delimiter used to separate cookie file entries.") | 67 | "Delimiter used to separate cookie file entries.") |
| 58 | 68 | ||
| 59 | (defvar cookie-cache (make-vector 511 0) | 69 | (defvar cookie-cache (make-vector 511 0) |
| 60 | "Cache of cookie files that have already been snarfed.") | 70 | "Cache of cookie files that have already been snarfed.") |
| 61 | 71 | ||
| 72 | (defun cookie-check-file (file) | ||
| 73 | "Return either FILE or `cookie-file'. | ||
| 74 | Signal an error if the result is nil or not readable." | ||
| 75 | (or (setq file (or file cookie-file)) (user-error "No phrase file specified")) | ||
| 76 | (or (file-readable-p file) (user-error "Cannot read file `%s'" file)) | ||
| 77 | file) | ||
| 78 | |||
| 62 | ;;;###autoload | 79 | ;;;###autoload |
| 63 | (defun cookie (phrase-file startmsg endmsg) | 80 | (defun cookie (phrase-file &optional startmsg endmsg) |
| 64 | "Return a random phrase from PHRASE-FILE. | 81 | "Return a random phrase from PHRASE-FILE. |
| 65 | When the phrase file is read in, display STARTMSG at the beginning | 82 | When the phrase file is read in, display STARTMSG at the beginning |
| 66 | of load, ENDMSG at the end." | 83 | of load, ENDMSG at the end. |
| 67 | (let ((cookie-vector (cookie-snarf phrase-file startmsg endmsg))) | 84 | Interactively, PHRASE-FILE defaults to `cookie-file', unless that |
| 68 | (shuffle-vector cookie-vector) | 85 | is nil or a prefix argument is used." |
| 69 | (aref cookie-vector 0))) | 86 | (interactive (list (if (or current-prefix-arg (not cookie-file)) |
| 87 | (read-file-name "Cookie file: " nil | ||
| 88 | cookie-file t cookie-file) | ||
| 89 | cookie-file) nil nil)) | ||
| 90 | (setq phrase-file (cookie-check-file phrase-file)) | ||
| 91 | (let ((cookie-vector (cookie-snarf phrase-file startmsg endmsg)) | ||
| 92 | res) | ||
| 93 | (cookie-shuffle-vector cookie-vector) | ||
| 94 | (setq res (aref cookie-vector 0)) | ||
| 95 | (if (called-interactively-p 'interactive) | ||
| 96 | (message "%s" res) | ||
| 97 | res))) | ||
| 70 | 98 | ||
| 71 | ;;;###autoload | 99 | ;;;###autoload |
| 72 | (defun cookie-insert (phrase-file &optional count startmsg endmsg) | 100 | (defun cookie-insert (phrase-file &optional count startmsg endmsg) |
| 73 | "Insert random phrases from PHRASE-FILE; COUNT of them. | 101 | "Insert random phrases from PHRASE-FILE; COUNT of them. |
| 74 | When the phrase file is read in, display STARTMSG at the beginning | 102 | When the phrase file is read in, display STARTMSG at the beginning |
| 75 | of load, ENDMSG at the end." | 103 | of load, ENDMSG at the end." |
| 104 | (setq phrase-file (cookie-check-file phrase-file)) | ||
| 76 | (let ((cookie-vector (cookie-snarf phrase-file startmsg endmsg))) | 105 | (let ((cookie-vector (cookie-snarf phrase-file startmsg endmsg))) |
| 77 | (shuffle-vector cookie-vector) | 106 | (cookie-shuffle-vector cookie-vector) |
| 78 | (let ((start (point))) | 107 | (let ((start (point))) |
| 79 | (insert ?\n) | 108 | (insert ?\n) |
| 80 | (cookie1 (min (- (length cookie-vector) 1) (or count 1)) cookie-vector) | 109 | (cookie1 (min (- (length cookie-vector) 1) (or count 1)) cookie-vector) |
| @@ -89,12 +118,11 @@ of load, ENDMSG at the end." | |||
| 89 | (cookie1 (1- arg) cookie-vec)))) | 118 | (cookie1 (1- arg) cookie-vec)))) |
| 90 | 119 | ||
| 91 | ;;;###autoload | 120 | ;;;###autoload |
| 92 | (defun cookie-snarf (phrase-file startmsg endmsg) | 121 | (defun cookie-snarf (phrase-file &optional startmsg endmsg) |
| 93 | "Reads in the PHRASE-FILE, returns it as a vector of strings. | 122 | "Reads in the PHRASE-FILE, returns it as a vector of strings. |
| 94 | Emit STARTMSG and ENDMSG before and after. Caches the result; second | 123 | Emit STARTMSG and ENDMSG before and after. Caches the result; second |
| 95 | and subsequent calls on the same file won't go to disk." | 124 | and subsequent calls on the same file won't go to disk." |
| 96 | (or (file-readable-p phrase-file) | 125 | (setq phrase-file (cookie-check-file phrase-file)) |
| 97 | (error "Cannot read file `%s'" phrase-file)) | ||
| 98 | (let ((sym (intern-soft phrase-file cookie-cache))) | 126 | (let ((sym (intern-soft phrase-file cookie-cache))) |
| 99 | (and sym (not (equal (symbol-function sym) | 127 | (and sym (not (equal (symbol-function sym) |
| 100 | (nth 5 (file-attributes phrase-file)))) | 128 | (nth 5 (file-attributes phrase-file)))) |
| @@ -104,27 +132,25 @@ and subsequent calls on the same file won't go to disk." | |||
| 104 | (if sym | 132 | (if sym |
| 105 | (symbol-value sym) | 133 | (symbol-value sym) |
| 106 | (setq sym (intern phrase-file cookie-cache)) | 134 | (setq sym (intern phrase-file cookie-cache)) |
| 107 | (message "%s" startmsg) | 135 | (if startmsg (message "%s" startmsg)) |
| 108 | (save-excursion | 136 | (fset sym (nth 5 (file-attributes phrase-file))) |
| 109 | (let ((buf (generate-new-buffer "*cookie*")) | 137 | (let (result) |
| 110 | (result nil)) | 138 | (with-temp-buffer |
| 111 | (set-buffer buf) | ||
| 112 | (fset sym (nth 5 (file-attributes phrase-file))) | ||
| 113 | (insert-file-contents (expand-file-name phrase-file)) | 139 | (insert-file-contents (expand-file-name phrase-file)) |
| 114 | (re-search-forward cookie-delimiter) | 140 | (re-search-forward cookie-delimiter) |
| 115 | (while (progn (skip-chars-forward " \t\n\r\f") (not (eobp))) | 141 | (while (progn (skip-chars-forward " \t\n\r\f") (not (eobp))) |
| 116 | (let ((beg (point))) | 142 | (let ((beg (point))) |
| 117 | (re-search-forward cookie-delimiter) | 143 | (re-search-forward cookie-delimiter) |
| 118 | (setq result (cons (buffer-substring beg (match-beginning 0)) | 144 | (setq result (cons (buffer-substring beg (match-beginning 0)) |
| 119 | result)))) | 145 | result))))) |
| 120 | (kill-buffer buf) | 146 | (if endmsg (message "%s" endmsg)) |
| 121 | (message "%s" endmsg) | 147 | (set sym (apply 'vector result)))))) |
| 122 | (set sym (apply 'vector result))))))) | ||
| 123 | 148 | ||
| 124 | (defun read-cookie (prompt phrase-file startmsg endmsg &optional require-match) | 149 | (defun cookie-read (prompt phrase-file &optional startmsg endmsg require-match) |
| 125 | "Prompt with PROMPT and read with completion among cookies in PHRASE-FILE. | 150 | "Prompt with PROMPT and read with completion among cookies in PHRASE-FILE. |
| 126 | STARTMSG and ENDMSG are passed along to `cookie-snarf'. | 151 | STARTMSG and ENDMSG are passed along to `cookie-snarf'. |
| 127 | Optional fifth arg REQUIRE-MATCH non-nil forces a matching cookie." | 152 | Argument REQUIRE-MATCH non-nil forces a matching cookie." |
| 153 | (setq phrase-file (cookie-check-file phrase-file)) | ||
| 128 | ;; Make sure the cookies are in the cache. | 154 | ;; Make sure the cookies are in the cache. |
| 129 | (or (intern-soft phrase-file cookie-cache) | 155 | (or (intern-soft phrase-file cookie-cache) |
| 130 | (cookie-snarf phrase-file startmsg endmsg)) | 156 | (cookie-snarf phrase-file startmsg endmsg)) |
| @@ -141,24 +167,85 @@ Optional fifth arg REQUIRE-MATCH non-nil forces a matching cookie." | |||
| 141 | (put sym 'completion-alist alist)))) | 167 | (put sym 'completion-alist alist)))) |
| 142 | nil require-match nil nil)) | 168 | nil require-match nil nil)) |
| 143 | 169 | ||
| 144 | ; Thanks to Ian G Batten <BattenIG@CS.BHAM.AC.UK> | 170 | (define-obsolete-function-alias 'read-cookie 'cookie-read "24.4") |
| 145 | ; [of the University of Birmingham Computer Science Department] | 171 | |
| 146 | ; for the iterative version of this shuffle. | 172 | ;; Thanks to Ian G Batten <BattenIG@CS.BHAM.AC.UK> |
| 147 | ; | 173 | ;; [of the University of Birmingham Computer Science Department] |
| 148 | ;;;###autoload | 174 | ;; for the iterative version of this shuffle. |
| 149 | (defun shuffle-vector (vector) | 175 | (defun cookie-shuffle-vector (vector) |
| 150 | "Randomly permute the elements of VECTOR (all permutations equally likely)." | 176 | "Randomly permute the elements of VECTOR (all permutations equally likely)." |
| 151 | (let ((i 0) | 177 | (let ((len (length vector)) |
| 152 | j | 178 | j temp) |
| 153 | temp | 179 | (dotimes (i len vector) |
| 154 | (len (length vector))) | 180 | (setq j (+ i (random (- len i))) |
| 155 | (while (< i len) | 181 | temp (aref vector i)) |
| 156 | (setq j (+ i (random (- len i)))) | ||
| 157 | (setq temp (aref vector i)) | ||
| 158 | (aset vector i (aref vector j)) | 182 | (aset vector i (aref vector j)) |
| 159 | (aset vector j temp) | 183 | (aset vector j temp)))) |
| 160 | (setq i (1+ i)))) | 184 | |
| 161 | vector) | 185 | (define-obsolete-function-alias 'shuffle-vector 'cookie-shuffle-vector "24.4") |
| 186 | |||
| 187 | |||
| 188 | (defun cookie-apropos (regexp phrase-file) | ||
| 189 | "Return a list of all entries matching REGEXP from PHRASE-FILE. | ||
| 190 | Interactively, PHRASE-FILE defaults to `cookie-file', unless that | ||
| 191 | is nil or a prefix argument is used. | ||
| 192 | If called interactively, display a list of matches." | ||
| 193 | (interactive (list (read-regexp "Apropos phrase (regexp): ") | ||
| 194 | (if (or current-prefix-arg (not cookie-file)) | ||
| 195 | (read-file-name "Cookie file: " nil | ||
| 196 | cookie-file t cookie-file) | ||
| 197 | cookie-file))) | ||
| 198 | (setq phrase-file (cookie-check-file phrase-file)) | ||
| 199 | ;; Make sure phrases are loaded. | ||
| 200 | (cookie phrase-file) | ||
| 201 | (let* ((case-fold-search t) | ||
| 202 | (cookie-table-symbol (intern phrase-file cookie-cache)) | ||
| 203 | (string-table (symbol-value cookie-table-symbol)) | ||
| 204 | (matches nil) | ||
| 205 | (len (length string-table)) | ||
| 206 | (i 0)) | ||
| 207 | (save-match-data | ||
| 208 | (while (< i len) | ||
| 209 | (and (string-match regexp (aref string-table i)) | ||
| 210 | (setq matches (cons (aref string-table i) matches))) | ||
| 211 | (setq i (1+ i)))) | ||
| 212 | (and matches | ||
| 213 | (setq matches (sort matches 'string-lessp))) | ||
| 214 | (and (called-interactively-p 'interactive) | ||
| 215 | (cond ((null matches) | ||
| 216 | (message "No matches found.")) | ||
| 217 | (t | ||
| 218 | (let ((l matches)) | ||
| 219 | (with-output-to-temp-buffer "*Cookie Apropos*" | ||
| 220 | (while l | ||
| 221 | (princ (car l)) | ||
| 222 | (setq l (cdr l)) | ||
| 223 | (and l (princ "\n\n"))) | ||
| 224 | (help-print-return-message)))))) | ||
| 225 | matches)) | ||
| 226 | |||
| 227 | |||
| 228 | (declare-function doctor-ret-or-read "doctor" (arg)) | ||
| 229 | |||
| 230 | (defun cookie-doctor (phrase-file) | ||
| 231 | "Feed cookie phrases from PHRASE-FILE to the doctor. | ||
| 232 | Interactively, PHRASE-FILE defaults to `cookie-file', unless that | ||
| 233 | is nil or a prefix argument is used." | ||
| 234 | (interactive (list (if (or current-prefix-arg (not cookie-file)) | ||
| 235 | (read-file-name "Cookie file: " nil | ||
| 236 | cookie-file t cookie-file) | ||
| 237 | cookie-file))) | ||
| 238 | (setq phrase-file (cookie-check-file phrase-file)) | ||
| 239 | (doctor) ; start the psychotherapy | ||
| 240 | (message "") | ||
| 241 | (switch-to-buffer "*doctor*") | ||
| 242 | (sit-for 0) | ||
| 243 | (while (not (input-pending-p)) | ||
| 244 | (insert (cookie phrase-file)) | ||
| 245 | (sit-for 0) | ||
| 246 | (doctor-ret-or-read 1) | ||
| 247 | (doctor-ret-or-read 1))) | ||
| 248 | |||
| 162 | 249 | ||
| 163 | (provide 'cookie1) | 250 | (provide 'cookie1) |
| 164 | 251 | ||