(parse_charset_map): Remove an unused variable.
[bpt/emacs.git] / lisp / play / cookie1.el
index ee5521a..cd3c715 100644 (file)
@@ -4,7 +4,7 @@
 
 ;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
 ;; Maintainer: FSF
-;; Keywords: games
+;; Keywords: games, extensions
 ;; Created: Mon Mar 22 17:06:26 1993
 
 ;; This file is part of GNU Emacs.
@@ -20,8 +20,9 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 
@@ -30,8 +31,7 @@
 ;; the NSA Trunk Trawler.
 ;;
 ;; The two entry points are `cookie' and `cookie-insert'.  The helper
-;; functions `pick-random' and `shuffle-vector' may be of interest to
-;; programmers.
+;; function `shuffle-vector' may be of interest to programmers.
 ;;
 ;; The code expects phrase files to be in one of two formats:
 ;;
 ;; formats could be supported by adding alternates to the regexp
 ;; `cookie-delimiter'.
 ;;
+;; strfile(1) is the program used to compile the files for fortune(6).
+;; In order to achieve total compatibility with strfile(1), cookie files
+;; should start with two consecutive delimiters (and no comment).
+;;
 ;; This code derives from Steve Strassman's 1987 spook.el package, but
 ;; has been generalized so that it supports multiple simultaneous
 ;; cookie databases and fortune files.  It is intended to be called
@@ -57,7 +61,7 @@
 ; Randomize the seed in the random number generator.
 (random t)
 
-(defconst cookie-delimiter "\n%%\n\\|\0"
+(defconst cookie-delimiter "\n%%\n\\|\n%\n\\|\0"
   "Delimiter used to separate cookie file entries.")
 
 (defvar cookie-cache (make-vector 511 0)
 
 ;;;###autoload
 (defun cookie (phrase-file startmsg endmsg)
-  "Return a random phrase from PHRASE-FILE.  When the phrase file
-is read in, display STARTMSG at beginning of load, ENDMSG at end."
+  "Return a random phrase from PHRASE-FILE.
+When the phrase file is read in, display STARTMSG at the beginning
+of load, ENDMSG at the end."
   (let ((cookie-vector (cookie-snarf phrase-file startmsg endmsg)))
     (shuffle-vector cookie-vector)
     (aref cookie-vector 1)))
 
 ;;;###autoload
 (defun cookie-insert (phrase-file &optional count startmsg endmsg)
-  "Insert random phrases from PHRASE-FILE; COUNT of them.  When the phrase file
-is read in, display STARTMSG at beginning of load, ENDMSG at end."
+  "Insert random phrases from PHRASE-FILE; COUNT of them.
+When the phrase file is read in, display STARTMSG at the beginning
+of load, ENDMSG at the end."
   (let ((cookie-vector (cookie-snarf phrase-file startmsg endmsg)))
     (shuffle-vector cookie-vector)
     (let ((start (point)))
@@ -92,9 +98,9 @@ is read in, display STARTMSG at beginning of load, ENDMSG at end."
 
 ;;;###autoload
 (defun cookie-snarf (phrase-file startmsg endmsg)
-  "Reads in the PHRASE-FILE, returns it as a vector of strings.  Emit
-STARTMSG and ENDMSG before and after.  Caches the result; second and
-subsequent calls on the same file won't go to disk."
+  "Reads in the PHRASE-FILE, returns it as a vector of strings.
+Emit STARTMSG and ENDMSG before and after.  Caches the result; second
+and subsequent calls on the same file won't go to disk."
   (let ((sym (intern-soft phrase-file cookie-cache)))
     (and sym (not (equal (symbol-function sym)
                         (nth 5 (file-attributes phrase-file))))
@@ -104,7 +110,7 @@ subsequent calls on the same file won't go to disk."
     (if sym
        (symbol-value sym)
       (setq sym (intern phrase-file cookie-cache))
-      (message startmsg)
+      (message "%s" startmsg)
       (save-excursion
        (let ((buf (generate-new-buffer "*cookie*"))
              (result nil))
@@ -115,15 +121,31 @@ subsequent calls on the same file won't go to disk."
          (while (progn (skip-chars-forward " \t\n\r\f") (not (eobp)))
            (let ((beg (point)))
              (re-search-forward cookie-delimiter)
-             (setq result (cons (buffer-substring beg (1- (point)))
+             (setq result (cons (buffer-substring beg (match-beginning 0))
                                 result))))
          (kill-buffer buf)
-         (message endmsg)
+         (message "%s" endmsg)
          (set sym (apply 'vector result)))))))
 
-(defun pick-random (n)
-  "Returns a random number from 0 to N-1 inclusive."
-  (% (logand 0777777 (random)) n))
+(defun read-cookie (prompt phrase-file startmsg endmsg &optional require-match)
+  "Prompt with PROMPT and read with completion among cookies in PHRASE-FILE.
+STARTMSG and ENDMSG are passed along to `cookie-snarf'.
+Optional fifth arg REQUIRE-MATCH non-nil forces a matching cookie."
+  ;; Make sure the cookies are in the cache.
+  (or (intern-soft phrase-file cookie-cache)
+      (cookie-snarf phrase-file startmsg endmsg))
+  (completing-read prompt
+                  (let ((sym (intern phrase-file cookie-cache)))
+                    ;; We cache the alist form of the cookie in a property.
+                    (or (get sym 'completion-alist)
+                        (let* ((alist nil)
+                               (vec (cookie-snarf phrase-file
+                                                  startmsg endmsg))
+                               (i (length vec)))
+                          (while (> (setq i (1- i)) 0)
+                            (setq alist (cons (list (aref vec i)) alist)))
+                          (put sym 'completion-alist alist))))
+                  nil require-match nil nil))
 
 ; Thanks to Ian G Batten <BattenIG@CS.BHAM.AC.UK>
 ; [of the University of Birmingham Computer Science Department]
@@ -131,13 +153,13 @@ subsequent calls on the same file won't go to disk."
 ;
 ;;;###autoload
 (defun shuffle-vector (vector)
-  "Randomly permute the elements of VECTOR (all permutations equally likely)"
+  "Randomly permute the elements of VECTOR (all permutations equally likely)."
   (let ((i 0)
        j
        temp
        (len (length vector)))
     (while (< i len)
-      (setq j (+ i (pick-random (- len i))))
+      (setq j (+ i (random (- len i))))
       (setq temp (aref vector i))
       (aset vector i (aref vector j))
       (aset vector j temp)