diff lisp/bookmark.el @ 4537:14f38c0332a4

entered into RCS
author Richard M. Stallman <rms@gnu.org>
date Tue, 10 Aug 1993 20:35:31 +0000
parents
children 2507541ef88d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/bookmark.el	Tue Aug 10 20:35:31 1993 +0000
@@ -0,0 +1,776 @@
+;;; bookmark.el --- set bookmarks, jump to them later.
+
+;; Copyright (C) 1993 Free Software Foundation, Inc.
+
+;; Author: Karl Fogel <kfogel@cs.oberlin.edu>
+;; Maintainer: FSF
+;; Created: July, 1993
+;; Version: 1.7.2
+;; Keywords: bookmarks, placeholders
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; 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.
+
+;; Thanks to David Bremner <bremner@cs.sfu.ca> for thinking of and
+;; then implementing the bookmark-current-bookmark idea.  He even
+;; sent *patches*, bless his soul... 
+
+;; Thanks to Gregory M. Saunders <saunders@cis.ohio-state.edu> for
+;; fixing and improving bookmark-time-to-save-p.
+
+;; Based on info-bookmark.el, by Karl Fogel and Ken Olstad
+;; <olstad@msc.edu>.
+
+;; LCD Archive Entry:
+;; bookmark|Karl Fogel|kfogel@cs.oberlin.edu|
+;; Setting bookmarks in files or directories, jumping to them later.|
+;; 16-July-93|Version: 1.7.2|~/misc/bookmark.el.Z|
+
+;; FAVORITE CHINESE RESTAURANT: 
+;; Boy, that's a tough one.  Probably Hong Min, or maybe Emperor's
+;; Choice (both in Chicago's Chinatown).  Well, both.  How about you?
+
+;;; Commentary on code:
+
+;; bookmark alist format:
+;;               (...
+;;                (bookmark-name (filename
+;;                                string-in-front
+;;                                string-behind
+;;                                point))
+;;                ...)
+;;
+;; bookmark-name is the string the user gives the bookmark and
+;; accesses it by from then on.  filename is the location of the file
+;; in which the bookmark is set.  string-in-front is a string of
+;; `bookmark-search-size' chars of context in front of the point the
+;; bookmark is set at, string-behind is the same thing after the
+;; point.  bookmark-jump will search for string-behind and
+;; string-in-front in case the file has changed since the bookmark was
+;; set.  It will attempt to place the user before the changes, if
+;; there were any.
+
+;;; Code:
+
+;; Added  for lucid emacs  compatibility, db
+(or (fboundp 'defalias)  (fset 'defalias 'fset))
+
+;; these are the distribution keybindings suggested by RMS, everything
+;; else will be done with M-x or the menubar:
+(define-key ctl-x-map "rb" 'bookmark-jump)
+(define-key ctl-x-map "rm" 'bookmark-set)
+(define-key ctl-x-map "rl" 'bookmark-locate)
+
+;; define the map, so it can be bound by those who desire to do so:
+
+(defvar bookmark-map nil "This is a keymap containing bookmark
+functions.  It is not bound to any key by default: to bind it so 
+that you have a bookmark prefix, just use global-set-key and bind a
+key of your choice to \'bookmark-map.  All interactive bookmark
+functions have a binding in this keymap.")
+
+(define-prefix-command 'bookmark-map)
+
+;; Read the help on all of these functions for details...
+;; "x" marks the spot!
+(define-key bookmark-map "x" 'bookmark-set)
+(define-key bookmark-map "j" 'bookmark-jump)
+(define-key bookmark-map "i" 'bookmark-insert)
+(define-key bookmark-map "f" 'bookmark-locate) ; "f" for "find"
+(define-key bookmark-map "n" 'bookmark-rename) ; "n" for "new name"
+;; deletes bookmarks
+(define-key bookmark-map "d" 'bookmark-delete)
+;; loads new file
+(define-key bookmark-map "l" 'bookmark-load)
+;; saves them in file
+(define-key bookmark-map "w" 'bookmark-write)  
+(define-key bookmark-map "s" 'bookmark-save)
+
+;; just add the hook to make sure that people don't lose bookmarks
+;; when they kill Emacs, unless they don't want to save them.
+
+(add-hook 'kill-emacs-hook
+          (function
+           (lambda ()
+             (and (featurep 'bookmark)
+                  bookmark-alist
+                  (bookmark-time-to-save-p t)
+                  (bookmark-save)))))
+
+;; more stuff added by db.
+(defvar bookmark-current-bookmark nil 
+  "Store the bookmark most recently set, jumped to, or renamed.
+Buffer local, used to make moving a bookmark forward  through a 
+file easier.")
+
+(make-variable-buffer-local 'bookmark-current-bookmark)
+
+(defvar bookmark-save-flag t
+  "*Nil means never save bookmarks, except when bookmark-save is
+explicitly called \(\\[bookmark-save]\).
+
+t means save bookmarks when Emacs is killed.
+
+Otherise, it should be a number that is the frequency with which the
+bookmark list is saved \(i.e.: the number of times which Emacs\'
+bookmark list may be modified before it is automatically saved.\).  If
+it is a number, Emacs will also automatically save bookmarks when it
+is killed.
+
+Therefore, the way to get it to save every time you make or delete a
+bookmark is to set this variable to 1 \(or 0, which produces the same
+behavior.\)
+
+To specify the file in which to save them, modify the variable
+bookmark-file, which is \"~/.emacs-bkmrks\" by default.")
+
+(defvar bookmark-alist-modification-count 0
+  "Number of times the bookmark list has been modified since last
+saved.")
+
+(defvar bookmark-file "~/.emacs-bkmrks" 
+  "*File in which to save bookmarks by default.")
+
+(defvar bookmark-completion-ignore-case t
+  "*Non-nil means that the various bookmark functions that
+do completion will be case-insensitive in completion.")
+
+(defvar bookmark-search-size 500 "Number of chars resolution used
+in creating tag strings to record a bookmark.  Bookmark functions will
+search for these strings in deciding where to jump to, to deal with
+changing values of point.  I can\'t think of any reason you would want
+to modify this, and doing so might have side effects, so on your own
+head be it...")
+
+(defvar bookmark-alist ()
+  "Association list of bookmarks.
+You probably don't want to change the value of this alist yourself;
+instead, let the various bookmark functions do it for you.")
+
+(defvar bookmark-current-point 0)
+(defvar bookmark-yank-point 0)
+(defvar bookmark-current-buffer nil)
+
+(defun bookmark-set (&optional parg)
+  "Set a bookmark named NAME inside a file.  With prefix arg, will not
+overwrite a bookmark that has the same name as NAME if such a bookmark
+already exists, but instead will \"push\" the new bookmark onto the
+bookmark alist.  Thus the most recently set bookmark with name NAME would
+be the one in effect at any given time, but the others are still there,
+should you decide to delete the most recent one.
+
+To yank words from the text of the buffer and use them as part of the
+bookmark name, type C-w while setting a bookmark.  Successive C-w\'s
+yank successive words.
+
+Typing C-v inserts the name of the current file being visited. Typing
+C-u inserts the name of the last bookmark used in the buffer \(as an
+aid in using a single bookmark name to track your progress through a
+large file\).  If no bookmark was used, then C-u behaves like C-v and
+inserts the name of the file being visited.
+
+Use \\[bookmark-delete] to remove bookmarks \(you give it a name,
+and it removes only the first instance of a bookmark with that name from
+the list of bookmarks.\)"
+  (interactive "P")
+  (if (not (bookmark-buffer-file-name))
+      (error "Buffer not visiting a file or directory."))
+  (setq bookmark-current-point (point))
+  (setq bookmark-yank-point (point))
+  (setq bookmark-current-buffer (current-buffer))
+  (let ((str
+         (read-from-minibuffer
+          "Set bookmark: "
+	  nil
+          (let ((now-map (copy-keymap minibuffer-local-map)))
+            (progn (define-key now-map  "\C-w" 
+                     'bookmark-yank-word)
+                   (define-key now-map  "\C-v" 
+                     'bookmark-insert-current-file-name)
+                   (define-key now-map  "\C-u" 
+                     'bookmark-insert-current-bookmark))
+	    now-map))))
+    (progn
+      (bookmark-make parg str)
+      (setq bookmark-current-bookmark str)      
+      (goto-char bookmark-current-point))))
+
+(defun bookmark-insert-current-bookmark ()
+  ;; insert this buffer's value of bookmark-current-bookmark, default
+  ;; to file name if it's nil.
+  (interactive)
+  (let ((str
+	 (save-excursion
+	   (set-buffer bookmark-current-buffer)
+	   bookmark-current-bookmark)))
+    (if str (insert str) (bookmark-insert-current-file-name))))
+
+(defun bookmark-insert-current-file-name ()
+  ;; insert the name (sans path) of the current file into the bookmark
+  ;; name that is being set.
+  (interactive)
+  (let ((str (save-excursion
+	       (set-buffer bookmark-current-buffer)
+	       (bookmark-buffer-file-name))))
+    (insert (substring 
+	     str
+	     (1+ (string-match 
+		  "\\(/[^/]*\\)/*$"
+		  str))))))
+
+(defun bookmark-yank-word ()
+  (interactive)
+  ;; get the next word from the buffer and append it to the name of
+  ;; the bookmark currently being set.
+  (let ((string (save-excursion
+                  (set-buffer bookmark-current-buffer)
+                  (goto-char bookmark-yank-point)
+                  (buffer-substring
+                   (point)
+                   (save-excursion
+                     (forward-word 1)
+                     (setq bookmark-yank-point (point)))))))
+    (insert string)))
+
+(defun bookmark-make (parg str)
+  (if (and (assoc str bookmark-alist) (not parg))
+      ;; already existing boookmark under that name and
+      ;; no prefix arg means just overwrite old bookmark
+      (setcdr (assoc str bookmark-alist)
+              (list (bookmark-make-cell)))
+    
+    ;; otherwise just cons it onto the front (either the bookmark
+    ;; doesn't exist already, or there is no prefix arg.  In either
+    ;; case, we want the new bookmark consed onto the alist...)
+    
+    (setq bookmark-alist
+          (cons
+           (list str 
+                 (bookmark-make-cell))
+           bookmark-alist)))
+  ;; Added by db
+  (setq bookmark-current-bookmark str)
+  (setq bookmark-alist-modification-count
+        (1+ bookmark-alist-modification-count))
+  (if (bookmark-time-to-save-p)
+      (bookmark-save)))
+
+(defun bookmark-make-cell ()
+  ;; make the cell that is the cdr of a bookmark alist element.  It
+  ;; looks like this:
+  ;; (filename search-forward-str search-back-str point)
+  (list
+   (bookmark-buffer-file-name)
+   (if (>= (- (point-max) (point)) bookmark-search-size)
+       (buffer-substring 
+        (point)
+        (+ (point) bookmark-search-size))
+     nil)
+   (if (>= (- (point) (point-min)) bookmark-search-size)
+       (buffer-substring 
+        (point)
+        (- (point) bookmark-search-size))
+     nil)
+   (point)))
+
+(defun bookmark-buffer-file-name ()
+  (or
+   buffer-file-name
+   (if (and (boundp 'dired-directory) dired-directory)
+       (if (stringp dired-directory)
+	   dired-directory
+	 (car dired-directory)))))
+
+(defun bookmark-try-default-file ()
+  (if (and (null bookmark-alist)
+	   (file-readable-p (expand-file-name bookmark-file)))
+      (bookmark-load bookmark-file)))
+  
+(defun bookmark-jump (str)
+    "Go to the location saved in the bookmark BOOKMARK.  You may have a
+problem using this function if the value of variable bookmark-alist
+is nil.  If that happens, you need to load in some bookmarks.  See
+help on function bookmark-load for more about this."
+    (interactive (progn
+                 (bookmark-try-default-file)
+                 (let ((completion-ignore-case
+                        bookmark-completion-ignore-case))
+                   (list (completing-read
+                          "Jump to bookmark: "
+                          bookmark-alist
+                          nil
+                          0)))))
+  (let ((whereto-list (car (cdr (assoc str bookmark-alist)))))
+    (let ((file (car whereto-list))
+          (forward-str (car (cdr whereto-list)))
+          (behind-str (car (cdr (cdr whereto-list))))
+          (place (car (cdr (cdr (cdr whereto-list))))))
+      (if (file-exists-p (expand-file-name file))
+          (progn 
+            (find-file (expand-file-name file))
+            (goto-char place)
+            ;; Go searching forward first.  Then, if forward-str exists and
+            ;; was found in the file, we can search backward for behind-str.
+            ;; Rationale is that if text was inserted between the two in the
+            ;; file, it's better to be put before it so you can read it,
+            ;; rather than after and remain perhaps unaware of the changes.
+            (if forward-str
+                (if (search-forward forward-str (point-max) t)
+                    (backward-char bookmark-search-size)))
+            (if behind-str
+                (if (search-backward behind-str (point-min) t)
+                    (forward-char bookmark-search-size)))
+            ;; added by db
+            (setq bookmark-current-bookmark str))
+        (error 
+         (concat "File "
+                 file
+                 " does not exist.  Suggest deleting bookmark \""
+                 str
+                 "\""))))))
+
+(defun bookmark-locate (str)
+  "Insert the name of the  file associated with BOOKMARK \(as opposed
+to the contents of that file\)."
+  (interactive (progn
+		 (bookmark-try-default-file)
+                 (let ((completion-ignore-case
+                        bookmark-completion-ignore-case))
+                   (list (completing-read
+                          "Insert bookmark location: "
+                          bookmark-alist
+                          nil
+                          0)))))
+  (insert (car (car (cdr (assoc str bookmark-alist))))))
+
+(defun bookmark-rename (old)
+  "Change the name of BOOKMARK to NEWNAME.  While you are entering
+the new name, consecutive C-w\'s will insert consectutive words from
+the text of the buffer into the new bookmark name, and C-v will insert
+the name of the file."
+  (interactive (progn
+		 (bookmark-try-default-file)
+                 (let ((completion-ignore-case
+                        bookmark-completion-ignore-case))
+                   (list (completing-read "Old bookmark name: "
+					  bookmark-alist
+					  nil
+					  0)))))
+  (progn
+    (setq bookmark-current-point (point))
+    (setq bookmark-yank-point (point))
+    (setq bookmark-current-buffer (current-buffer))
+    (let ((cell (assoc old bookmark-alist))
+	  (str
+	   (read-from-minibuffer 
+	    "New name: "
+	    nil
+	    (let ((now-map (copy-keymap minibuffer-local-map)))
+	      (progn (define-key now-map  "\C-w" 
+		       'bookmark-yank-word)
+		     (define-key now-map  "\C-v" 
+		       'bookmark-insert-current-file-name))
+	      now-map))))
+      (progn
+	(setcar cell str)
+	(setq bookmark-current-bookmark str)
+	(setq bookmark-alist-modification-count
+	      (1+ bookmark-alist-modification-count))
+	(if (bookmark-time-to-save-p)
+	    (bookmark-save))))))
+
+(defun bookmark-insert (str)
+  "Insert the text of the file pointed to by bookmark BOOKMARK.  You
+may have a problem using this function if the value of variable
+bookmark-alist is nil.  If that happens, you need to load in some
+bookmarks.  See help on function bookmark-load for more about this."
+  (interactive (progn
+                 (bookmark-try-default-file)
+                 (let ((completion-ignore-case
+                        bookmark-completion-ignore-case))
+                   (list (completing-read
+                          "Insert bookmark contents: "
+                          bookmark-alist
+                          nil
+                          0)))))
+  (let ((whereto-list (car (cdr (assoc str bookmark-alist)))))
+    (let ((file (car whereto-list)))
+      (if (file-readable-p (expand-file-name file))
+	  (let ((str-to-insert
+		 (save-excursion
+		   (find-file (expand-file-name file))
+		   (prog1
+		       (buffer-substring (point-min) (point-max))
+		     (bury-buffer))))
+		(orig-point (point)))
+	    (insert str-to-insert)
+	    (push-mark)	    
+	    (goto-char orig-point))
+	(error	
+	 (concat "File "
+                 file
+                 " does not exist.  Suggest deleting bookmark \""
+                 str
+                 "\""))))))
+
+(defun bookmark-delete (str)
+  "Delete the bookmark named NAME from the bookmark list.  Removes
+only the first instance of a bookmark with that name.  If there is
+another bookmark with the same name, it will become \"current\" as
+soon as the old one is removed from the bookmark list.  Defaults to
+the \"current\" bookmark \(that is, the one most recently set or
+jumped to in this file\).
+
+With a prefix argument, deletes all bookmarks \(will prompt for
+confirmation before such a drastic step, however.\)  If you then save
+the empty bookmark list, they will truly be deleted; otherwise you
+will revert to the bookmarks saved in the default bookmark file
+automatically the next time you jump to a bookmark, insert one, rename
+one, or kill Emacs."
+  (interactive (let ((completion-ignore-case
+		      bookmark-completion-ignore-case))
+		 (list
+		  (if current-prefix-arg
+		      nil
+		    (completing-read
+		     "Delete bookmark: "
+		     bookmark-alist
+		     nil
+		     0
+		     bookmark-current-bookmark)))))
+  (if (null str)
+      (if (y-or-n-p "Delete all bookmarks? ")
+          (progn
+            (setq bookmark-alist nil)
+            (message
+             (if (file-readable-p (expand-file-name bookmark-file))
+                 (format 
+                  "Will revert to bookmarks in %s, unless you save now."
+                  bookmark-file)
+               "All bookmarks deleted.")))
+        (message "No bookmarks deleted."))
+    (let ((will-go (assoc str bookmark-alist)))
+      (setq bookmark-alist (delq will-go bookmark-alist)))
+      ;; Added by db, nil bookmark-current-bookmark if the last
+      ;; occurence has been deleted
+    (or (assoc bookmark-current-bookmark bookmark-alist)
+	(setq bookmark-current-bookmark nil)))
+    (setq bookmark-alist-modification-count
+	  (1+ bookmark-alist-modification-count))
+    (if (bookmark-time-to-save-p)
+	(bookmark-save)))
+
+(defun bookmark-time-to-save-p (&optional last-time)
+  ;; By Gregory M. Saunders <saunders@cis.ohio-state.edu>
+  ;; finds out whether it's time to save bookmarks to a file, by
+  ;; examining the value of variable bookmark-save-flag, and maybe
+  ;; bookmark-alist-modification-count.  Returns t if they should be
+  ;; saved, nil otherwise.  if last-time is non-nil, then this is
+  ;; being called when emacs is killed.
+  (cond (last-time 
+	 (and (> bookmark-alist-modification-count 0)
+	      bookmark-save-flag))
+	((numberp bookmark-save-flag)
+	 (>= bookmark-alist-modification-count bookmark-save-flag))
+	(t
+	 nil)))
+
+(defun bookmark-write ()
+  (interactive)
+  (bookmark-save t))
+
+(defun bookmark-save (&optional parg file)
+  "Saves currently defined bookmarks in the file defined by
+the variable bookmark-file.  With a prefix arg, save it in file
+FILE.
+
+If you are calling this from Lisp, the two arguments are PREFIX-ARG
+and FILE, and if you just want it to write to the default file, then
+pass no arguments.  Or pass in nil and FILE, and it will save in FILE
+instead.  If you pass in one argument, and it is non-nil, then the
+user will be interactively queried for a file to save in.
+
+When you want to load in the bookmarks from a file, use bookmark-load,
+\\[bookmark-load].  That function will prompt you for a file,
+defaulting to the file defined by variable bookmark-file."
+  (interactive "P")
+  (cond
+   ((and (null parg) (null file))
+    ;;whether interactive or not, write to default file
+    (bookmark-write-file bookmark-file))
+   ((and (null parg) file)
+    ;;whether interactive or not, write to given file
+    (bookmark-write-file file))
+   ((and parg (not file))
+    ;;have been called interactively w/ prefix arg
+    (let ((file (read-file-name "File to save bookmarks in: ")))
+      (bookmark-write-file file)))
+   (t ; someone called us with prefix-arg *and* a file, so just write to file
+    (bookmark-write-file file)))
+  ;; signal that we have synced the bookmark file by setting this to
+  ;; 0.  If there was an error at any point before, it will not get
+  ;; set, which is what we want.
+  (setq bookmark-alist-modification-count 0))
+
+(defun bookmark-write-file (file)
+  (save-excursion
+    (message (format "Saving bookmarks to file %s." file))
+    (set-buffer (find-file-noselect file))
+    (goto-char (point-min))
+    (delete-region (point-min) (point-max))
+    (print bookmark-alist (current-buffer))
+    (write-file file)
+    (kill-buffer (current-buffer))))
+
+(defun bookmark-load (file &optional revert no-msg)
+  "Loads bookmarks from FILE, appending loaded bookmarks to the front
+of the list of bookmarks.  If optional second argument REVERT is
+non-nil, existing bookmarks are destroyed.  Optional third arg NO-MSG
+means don't display any messages while loading.
+
+If you load a file that doesn't contain a proper bookmark alist, you
+will corrupt Emacs\' bookmark list.  Generally, you should only load
+in files that were created with the bookmark functions in the first
+place.  If the bookmark alist does become corrupted, just delete all
+bookmarks and your master bookmark-file will be automatically loaded
+next time you try to go to a bookmark \(assuming that your bookmark
+file itself is not corrupt, this will solve the problem\)."
+  (interactive
+   (list (read-file-name
+          (format "Load bookmarks from: (%s) "
+                  bookmark-file)        
+          ;;Default might not be used often,
+          ;;but there's no better default, and
+          ;;I guess it's better than none at all.
+          "~/" bookmark-file 'confirm)))
+  (setq file (expand-file-name file))
+  (if (file-readable-p file)
+      (save-excursion
+        (if (null no-msg)
+	    (message (format "Loading bookmarks from %s..." file)))
+        (set-buffer (find-file-noselect file))
+        (goto-char (point-min))
+        (let ((blist (car (read-from-string
+                           (buffer-substring (point-min) (point-max))))))
+          (if (listp blist)
+              (progn
+                (if (not revert)
+                    (setq bookmark-alist-modification-count
+                          (1+ bookmark-alist-modification-count))
+                  (setq bookmark-alist-modification-count 0))
+                (setq bookmark-alist
+                      (append blist (if (not revert) bookmark-alist))))
+	    (error (format "Invalid bookmark list in %s." file))))
+	(kill-buffer (current-buffer))
+	(if (null no-msg)
+	    (message (format "Loading bookmarks from %s... done" file))))
+    (error (format "Cannot read bookmark file %s." file))))
+
+;;;; bookmark menu stuff ;;;;
+
+(defvar bookmark-enable-menus t
+  "*Non-nil means put a bookmark menu on the menu bar \(assuming that
+you are running Emacs under a windowing system, such as X\).")
+
+(defvar bookmark-menu-length 70 "*Maximum length of a bookmark name
+displayed on a menu.")
+
+(defun bookmark-make-menu-alist ()
+  (if (not bookmark-alist)
+      (if (file-readable-p bookmark-file)
+	  (bookmark-load bookmark-file)))
+  (if bookmark-alist
+      (mapcar (lambda (cell)
+		(let ((str (car cell)))
+		  (cons 
+		   (if (> (length str) bookmark-menu-length)
+		       (substring str 0 bookmark-menu-length)
+		     str)
+		   str)))
+	      bookmark-alist)
+    (error "No bookmarks currently set.")))
+
+(defun bookmark-make-menu-with-function (func-sym menu-label menu-str event)
+  ;; help function for making menus that need to apply a bookmark
+  ;; function to a string.
+  (let* ((menu (bookmark-make-menu-alist))
+	 (str (x-popup-menu event
+			    (list menu-label
+				  (cons menu-str
+					menu)))))
+    (if str
+	(apply func-sym (list str)))))
+
+(defun bookmark-menu-insert (event)
+  "Insert the text of the file pointed to by bookmark BOOKMARK.  You
+may have a problem using this function if the value of variable
+bookmark-alist is nil.  If that happens, you need to load in some
+bookmarks.  See help on function bookmark-load for more about this."
+  (interactive "e")
+  (bookmark-make-menu-with-function 'bookmark-insert
+				    "Bookmark Insert Menu"
+				    "--- Insert Contents ---"
+				    event))
+
+(defun bookmark-menu-jump (event)
+  "Go to the location saved in the bookmark BOOKMARK.  You may have a
+problem using this function if the value of variable bookmark-alist
+is nil.  If that happens, you need to load in some bookmarks.  See
+help on function bookmark-load for more about this."
+  (interactive "e")
+  (bookmark-make-menu-with-function 'bookmark-jump
+				    "Bookmark Jump Menu"
+				    "--- Jump to Bookmark ---"
+				    event))
+
+(defun bookmark-menu-locate (event)
+  "Insert the name of the  file associated with BOOKMARK \(as opposed
+to the contents of that file\)."
+  (interactive "e")
+  (bookmark-make-menu-with-function 'bookmark-locate
+				    "Bookmark Locate Menu"
+				    "--- Insert Location ---"
+				    event))
+
+(defun bookmark-menu-rename (event)
+  "Change the name of BOOKMARK to NEWNAME.  While you are entering
+the new name, consecutive C-w\'s will insert consectutive words from
+the text of the buffer into the new bookmark name, and C-v will insert
+the name of the file."
+  (interactive "e")
+  (bookmark-make-menu-with-function 'bookmark-rename
+				    "Bookmark Rename Menu"
+				    "--- Rename Bookmark ---"
+				    event))
+
+(defun bookmark-menu-delete (event)
+  "Delete the bookmark named NAME from the bookmark list.  Removes only
+the first instance of a bookmark with that name.  If there is another
+bookmark with the same name, it will become \"current\" as soon as the
+old one is removed from the bookmark list."
+  (interactive "e")
+  (bookmark-make-menu-with-function 'bookmark-delete
+				    "Bookmark Delete Menu"
+				    "--- Delete Bookmark ---"
+				    event))
+
+(defun bookmark-menu-delete-all ()
+  (interactive)
+  (let ((current-prefix-arg t))
+    (bookmark-delete nil)))
+
+(if (and bookmark-enable-menus window-system)
+    (progn
+      (defvar menu-bar-bookmark-map 
+	(make-sparse-keymap "Bookmark functions"))
+      
+      ;; make bookmarks appear toward the right side of the menu.
+      (if (boundp 'menu-bar-final-items)
+	  (if menu-bar-final-items
+	      (setq menu-bar-final-items 
+		    (cons 'bookmark menu-bar-final-items)))
+	(setq menu-bar-final-items '(bookmark)))
+
+      (define-key global-map [menu-bar bookmark]
+	(cons "Bookmarks" menu-bar-bookmark-map))
+
+      (define-key menu-bar-bookmark-map [load]
+	'(" Load a bookmark file" . bookmark-load))
+
+      (define-key menu-bar-bookmark-map [write]
+	'("Write \(to another file\)" . bookmark-write))
+
+      (define-key menu-bar-bookmark-map [save]
+	'("Save \(in default file\)" . bookmark-save))
+      
+      (define-key menu-bar-bookmark-map [delete-all]
+	'(" Delete all bookmarks" . bookmark-menu-delete-all))
+
+      (define-key menu-bar-bookmark-map [delete]
+	'("  Delete a bookmark" . bookmark-menu-delete))
+      
+      (define-key menu-bar-bookmark-map [rename]
+	'("   Rename bookmark" . bookmark-menu-rename))
+      
+      (define-key menu-bar-bookmark-map [locate]
+	'("   Insert location" . bookmark-menu-locate))
+      
+      (define-key menu-bar-bookmark-map [insert]
+	'("   Insert contents" . bookmark-menu-insert))
+      
+      (define-key menu-bar-bookmark-map [set]
+	'("    Set bookmark" . bookmark-set))
+      
+      (define-key menu-bar-bookmark-map [jump]
+	'("   Go to bookmark" . bookmark-menu-jump))))
+
+;; not using properties because they make the menu sluggish in coming
+;; up -- too many tests to make.  Instead, choosing a useless menu
+;; item just gets you an error now (see
+;; bookmark-make-menu-with-function) 
+;;      
+;;      (put 'bookmark-menu-jump 'menu-enable
+;;	   '(or bookmark-alist 
+;;		(and (file-readable-p bookmark-file)
+;;		     (progn (bookmark-load bookmark-file)
+;;			    bookmark-alist))))
+;;
+;;      (put 'bookmark-menu-insert 'menu-enable
+;;	   '(or bookmark-alist 
+;;		(and (file-readable-p bookmark-file)
+;;		     (progn (bookmark-load bookmark-file)
+;;			    bookmark-alist))))
+;;
+;;      (put 'bookmark-menu-locate 'menu-enable
+;;	   '(or bookmark-alist 
+;;		(and (file-readable-p bookmark-file)
+;;		     (progn (bookmark-load bookmark-file)
+;;			    bookmark-alist))))
+;;
+;;      (put 'bookmark-menu-rename 'menu-enable
+;;	   '(or bookmark-alist 
+;;		(and (file-readable-p bookmark-file)
+;;		     (progn (bookmark-load bookmark-file)
+;;			    bookmark-alist))))
+;;
+;;      (put 'bookmark-menu-delete 'menu-enable
+;;	   '(or bookmark-alist 
+;;		(and (file-readable-p bookmark-file)
+;;		     (progn (bookmark-load bookmark-file)
+;;			    bookmark-alist))))
+;;
+;;      (put 'bookmark-menu-save 'menu-enable
+;;	   '(or bookmark-alist
+;;		(and (file-readable-p bookmark-file)
+;;		     (progn (bookmark-load bookmark-file)
+;;			    bookmark-alist))))
+;;
+;;      (put 'bookmark-menu-write 'menu-enable
+;;	   '(or bookmark-alist 
+;;		(and (file-readable-p bookmark-file)
+;;		     (progn (bookmark-load bookmark-file)
+;;			    bookmark-alist))))
+
+;;;; end bookmark menu stuff ;;;;
+
+;; load the default bookmark file, if it exists, and the
+;; bookmark-alist is nil:
+(bookmark-try-default-file)
+
+
+(provide 'bookmark)
+      
+;;; bookmark.el ends here ;;;