]> code.delx.au - gnu-emacs/blobdiff - lisp/bookmark.el
* keymap.c (Fmake_sparse_keymap): Purecopy the name.
[gnu-emacs] / lisp / bookmark.el
index eef888288ce319469ca85d9ea988bd4c373e3d1b..331e392a9c701361fc6bc54b2a3abc3d31720cad 100644 (file)
@@ -278,7 +278,8 @@ will be used to open this bookmark instead of `bookmark-default-handler',
 whose calling discipline HANDLER-FUNC should of course match.")
 
 
-(defvar bookmarks-already-loaded nil)
+(defvar bookmarks-already-loaded nil
+  "Non-nil iff bookmarks have been loaded from `bookmark-default-file'.")
 
 
 ;; more stuff added by db.
@@ -299,11 +300,18 @@ through a file easier.")
   "Length of the context strings recorded on either side of a bookmark.")
 
 
-(defvar bookmark-current-point 0)
-(defvar bookmark-yank-point 0)
-(defvar bookmark-current-buffer nil)
+(defvar bookmark-current-buffer nil
+  "The buffer in which a bookmark is currently being set or renamed.
+Functions that insert strings into the minibuffer use this to know
+the source buffer for that information; see `bookmark-yank-word' and
+`bookmark-insert-current-bookmark' for example.")
+
+
+(defvar bookmark-yank-point 0
+  "The next point from which to pull source text for `bookmark-yank-word'.
+This point is in `bookmark-curent-buffer'.")
+
 
-(defvar Info-suffix-list)
 \f
 ;; Helper functions.
 
@@ -762,7 +770,6 @@ the list of bookmarks.\)"
 
     (bookmark-maybe-load-default-file)
 
-    (setq bookmark-current-point (point))
     (setq bookmark-yank-point (point))
     (setq bookmark-current-buffer (current-buffer))
 
@@ -777,9 +784,8 @@ the list of bookmarks.\)"
       (bookmark-store str (cdr record) no-overwrite)
 
       ;; Ask for an annotation buffer for this bookmark
-      (if bookmark-use-annotations
-          (bookmark-edit-annotation str)
-        (goto-char bookmark-current-point)))))
+      (when bookmark-use-annotations
+        (bookmark-edit-annotation str)))))
 
 (defun bookmark-kill-line (&optional newline-too)
   "Kill from point to end of line.
@@ -860,8 +866,7 @@ Lines beginning with `#' are ignored."
   (let ((annotation (buffer-substring-no-properties (point-min) (point-max)))
        (bookmark bookmark-annotation-name))
     (bookmark-set-annotation bookmark annotation)
-    (bookmark-bmenu-surreptitiously-rebuild-list)
-    (goto-char bookmark-current-point))
+    (bookmark-bmenu-surreptitiously-rebuild-list))
   (kill-buffer (current-buffer)))
 
 
@@ -873,8 +878,9 @@ BOOKMARK is a bookmark name (a string) or a bookmark record."
 
 
 (defun bookmark-insert-current-bookmark ()
-  "Insert this buffer's value of `bookmark-current-bookmark'.
-Default to file name if it's nil."
+  "Insert into the bookmark name currently being set the value of
+`bookmark-current-bookmark' in `bookmark-current-buffer', defaulting
+to the buffer's file name if `bookmark-current-bookmark' is nil."
   (interactive)
   (let ((str
         (with-current-buffer bookmark-current-buffer
@@ -906,8 +912,9 @@ way that is suitable as a bookmark name."
 
 
 (defun bookmark-yank-word ()
-  "Get the next word from the buffer and append it to the name of the
-bookmark currently being set, advancing point by one word."
+  "Get the next word from buffer `bookmark-current-buffer' and append
+it to the name of the bookmark currently being set, advancing
+`bookmark-yank-point' by one word." 
   (interactive)
   (let ((string (with-current-buffer bookmark-current-buffer
                   (goto-char bookmark-yank-point)
@@ -989,7 +996,7 @@ any annotations for this bookmark."
 
 
 ;;;###autoload
-(defun bookmark-jump (bookmark)
+(defun bookmark-jump (bookmark &optional display-func)
   "Jump to bookmark BOOKMARK (a point in some file).
 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
@@ -1002,48 +1009,28 @@ will then jump to the new location, as well as recording it in place
 of the old one in the permanent bookmark record.
 
 BOOKMARK may be a bookmark name (a string) or a bookmark record, but
-the latter is usually only used by programmatic callers."
+the latter is usually only used by programmatic callers.
+
+If DISPLAY-FUNC is non-nil, it is a function to invoke to display the
+bookmark.  It defaults to `switch-to-buffer'; a typical other value
+would be, e.g., `switch-to-buffer-other-window'."
   (interactive
    (list (bookmark-completing-read "Jump to bookmark"
                                   bookmark-current-bookmark)))
   (unless bookmark
     (error "No bookmark specified"))
   (bookmark-maybe-historicize-string bookmark)
-  (bookmark--jump-via bookmark 'switch-to-buffer))
+  (bookmark--jump-via bookmark (or display-func 'switch-to-buffer)))
 
 
 ;;;###autoload
 (defun bookmark-jump-other-window (bookmark)
   "Jump to BOOKMARK in another window.  See `bookmark-jump' for more."
   (interactive
-   (let ((bkm (bookmark-completing-read "Jump to bookmark (in another window)"
-                                        bookmark-current-bookmark)))
-     (if (> emacs-major-version 21)
-         (list bkm) bkm)))
-  (when bookmark
-    (bookmark-maybe-historicize-string bookmark)
-    (bookmark--jump-via bookmark 'switch-to-buffer-other-window)))
-
-
-(defun bookmark-file-or-variation-thereof (file)
-  "Return FILE (a string) if it exists, or return a reasonable
-variation of FILE if that exists.  Reasonable variations are checked
-by appending suffixes defined in `Info-suffix-list'.  If cannot find FILE
-nor a reasonable variation thereof, then still return FILE if it can
-be retrieved from a VC backend, else return nil."
-  (if (file-exists-p file)
-      file
-    (or
-     (progn (require 'info)  ; ensure Info-suffix-list is bound
-            (catch 'found
-              (mapc (lambda (elt)
-                      (let ((suffixed-file (concat file (car elt))))
-                        (if (file-exists-p suffixed-file)
-                            (throw 'found suffixed-file))))
-                    Info-suffix-list)
-              nil))
-     ;; Last possibility: try VC
-     (if (vc-backend file) file))))
+   (list (bookmark-completing-read "Jump to bookmark (in another window)"
+                                   bookmark-current-bookmark)))
+  (bookmark-jump bookmark 'switch-to-buffer-other-window))
+
 
 (defun bookmark-jump-noselect (bookmark)
   "Return the location pointed to by the bookmark BOOKMARK.
@@ -1061,9 +1048,13 @@ compatibility only."
 
 (defun bookmark-handle-bookmark (bookmark)
   "Call BOOKMARK's handler or `bookmark-default-handler' if it has none.
+BOOKMARK may be a bookmark name (a string) or a bookmark record.
+
 Changes current buffer and point and returns nil, or signals a `file-error'.
 
-BOOKMARK may be a bookmark name (a string) or a bookmark record."
+If BOOKMARK has no file, this is a no-op.  If BOOKMARK has a file, but
+that file no longer exists, then offer interactively to relocate BOOKMARK.
+"
   (condition-case err
       (funcall (or (bookmark-get-handler bookmark)
                    'bookmark-default-handler)
@@ -1072,57 +1063,57 @@ BOOKMARK may be a bookmark name (a string) or a bookmark record."
      ;; We were unable to find the marked file, so ask if user wants to
      ;; relocate the bookmark, else remind them to consider deletion.
      (when (stringp bookmark)
-       ;; `bookmark' can either be a bookmark name (found in
-       ;; `bookmark-alist') or a bookmark object.  If it's an object, we
-       ;; assume it's a bookmark used internally by some other package.
-       (let* ((file (bookmark-get-filename bookmark))
-              ;; If file is not a directory, this should be a no-op.
-              (display-name (directory-file-name file)))
+       ;; `bookmark' can be either a bookmark name (from `bookmark-alist')
+       ;; or a bookmark object.  If it's an object, we assume it's a
+       ;; bookmark used internally by some other package.
+       (let ((file (bookmark-get-filename bookmark)))
          (when file        ;Don't know how to relocate if there's no `file'.
-           (ding)
-           ;; Dialog boxes can accept a file target, but usually don't
-           ;; know how to accept a directory target (at least, this
-           ;; was true in Gnome on GNU/Linux, and Bug#4230 says it's
-           ;; true on Windows as well).  Thus, suppress file dialogs
-           ;; when relocating.
-           (let ((use-dialog-box nil)
-                 (use-file-dialog nil))
-             (if (y-or-n-p (concat display-name " nonexistent.  Relocate \""
-                                   bookmark "\"? "))
-                 (progn
-                   (bookmark-relocate bookmark)
-                   ;; Try again.
-                   (funcall (or (bookmark-get-handler bookmark)
-                                'bookmark-default-handler)
-                            (bookmark-get-bookmark bookmark)))
-               (message
-                "Bookmark not relocated; consider removing it \(%s\)." bookmark)
-               (signal (car err) (cdr err)))))))))
+           ;; If file is not a dir, directory-file-name just returns file.
+           (let ((display-name (directory-file-name file)))
+             (ding)
+             ;; Dialog boxes can accept a file target, but usually don't
+             ;; know how to accept a directory target (at least, this
+             ;; is true in Gnome on GNU/Linux, and Bug#4230 says it's
+             ;; true on Windows as well).  So we suppress file dialogs
+             ;; when relocating.
+             (let ((use-dialog-box nil)
+                   (use-file-dialog nil))
+               (if (y-or-n-p (concat display-name " nonexistent.  Relocate \""
+                                     bookmark "\"? "))
+                   (progn
+                     (bookmark-relocate bookmark)
+                     ;; Try again.
+                     (funcall (or (bookmark-get-handler bookmark)
+                                  'bookmark-default-handler)
+                              (bookmark-get-bookmark bookmark)))
+                 (message
+                  "Bookmark not relocated; consider removing it \(%s\)."
+                  bookmark)
+                 (signal (car err) (cdr err))))))))))
   ;; Added by db.
   (when (stringp bookmark)
     (setq bookmark-current-bookmark bookmark))
   nil)
 
+(put 'bookmark-error-no-filename
+     'error-conditions
+     '(error bookmark-errors bookmark-error-no-filename))
+(put 'bookmark-error-no-filename
+     'error-message
+     "Bookmark has no associated file (or directory)")
+
 (defun bookmark-default-handler (bmk-record)
   "Default handler to jump to a particular bookmark location.
 BMK-RECORD is a bookmark record, not a bookmark name (i.e., not a string).
 Changes current buffer and point and returns nil, or signals a `file-error'."
-  (let* ((file                   (bookmark-get-filename bmk-record))
-         (buf                    (bookmark-prop-get bmk-record 'buffer))
-         (forward-str            (bookmark-get-front-context-string bmk-record))
-         (behind-str             (bookmark-get-rear-context-string bmk-record))
-         (place                  (bookmark-get-position bmk-record)))
-    ;; FIXME: bookmark-file-or-variation-thereof was needed for Info files,
-    ;; but now that Info bookmarks are handled elsewhere it seems that we
-    ;; should be able to get rid of it.  --Stef
-    (if (not (if buf (buffer-live-p buf)
-               (setq file (bookmark-file-or-variation-thereof file))))
-        (signal 'file-error
-                `("Jumping to bookmark" "No such file or directory"
-                  (bookmark-get-filename bmk-record)))
-      (set-buffer (or buf (find-file-noselect file)))
+  (let ((file          (bookmark-get-filename bmk-record))
+        (forward-str   (bookmark-get-front-context-string bmk-record))
+        (behind-str    (bookmark-get-rear-context-string bmk-record))
+        (place         (bookmark-get-position bmk-record)))
+    (if (not file)
+        (signal 'bookmark-error-no-filename (list 'stringp file))
+      (set-buffer (find-file-noselect file))
       (if place (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
@@ -1186,7 +1177,7 @@ minibuffer history list `bookmark-history'."
 (defalias 'bookmark-locate 'bookmark-insert-location)
 
 (defun bookmark-location (bookmark)
-  "Return the name of the file associated with BOOKMARK.
+  "Return the name of the file associated with BOOKMARK, or nil if none.
 BOOKMARK may be a bookmark name (a string) or a bookmark record."
   (bookmark-maybe-load-default-file)
   (bookmark-get-filename bookmark))
@@ -1211,7 +1202,6 @@ name."
   (bookmark-maybe-historicize-string old)
   (bookmark-maybe-load-default-file)
 
-  (setq bookmark-current-point (point))
   (setq bookmark-yank-point (point))
   (setq bookmark-current-buffer (current-buffer))
   (let ((newname
@@ -1277,14 +1267,12 @@ probably because we were called from there."
     ;; occurrence has been deleted
     (or (bookmark-get-bookmark bookmark-current-bookmark 'noerror)
         (setq bookmark-current-bookmark nil)))
-  ;; Don't rebuild the list
-  (if batch
-      nil
-    (bookmark-bmenu-surreptitiously-rebuild-list)
-    (setq bookmark-alist-modification-count
-          (1+ bookmark-alist-modification-count))
-    (if (bookmark-time-to-save-p)
-        (bookmark-save))))
+  (unless batch
+    (bookmark-bmenu-surreptitiously-rebuild-list))
+  (setq bookmark-alist-modification-count
+        (1+ bookmark-alist-modification-count))
+  (when (bookmark-time-to-save-p)
+    (bookmark-save)))
 
 
 (defun bookmark-time-to-save-p (&optional final-time)
@@ -2034,10 +2022,6 @@ To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\
           (forward-char o-col))
       (goto-char o-point))
     (beginning-of-line)
-    (setq bookmark-alist-modification-count
-          (1+ bookmark-alist-modification-count))
-    (if (bookmark-time-to-save-p)
-        (bookmark-save))
     (message "Deleting bookmarks...done")
     ))
 
@@ -2049,7 +2033,6 @@ To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\
       (let ((bmrk (bookmark-bmenu-bookmark))
             (thispoint (point)))
         (bookmark-rename bmrk)
-        (bookmark-bmenu-list)
         (goto-char thispoint))))
 
 
@@ -2118,16 +2101,36 @@ strings returned are not."
 ;;;###autoload
 (defvar menu-bar-bookmark-map
   (let ((map (make-sparse-keymap "Bookmark functions")))
-    (define-key map [load]     '("Load a Bookmark File..." . bookmark-load))
-    (define-key map [write]    '("Save Bookmarks As..." . bookmark-write))
-    (define-key map [save]     '("Save Bookmarks" . bookmark-save))
-    (define-key map [edit]     '("Edit Bookmark List" . bookmark-bmenu-list))
-    (define-key map [delete]   '("Delete Bookmark..." . bookmark-delete))
-    (define-key map [rename]   '("Rename Bookmark..." . bookmark-rename))
-    (define-key map [locate]   '("Insert Location..." . bookmark-locate))
-    (define-key map [insert]   '("Insert Contents..." . bookmark-insert))
-    (define-key map [set]      '("Set Bookmark..." . bookmark-set))
-    (define-key map [jump]     '("Jump to Bookmark..." . bookmark-jump))
+    (define-key map [load]
+      `(menu-item ,(purecopy "Load a Bookmark File...") bookmark-load
+                 :help ,(purecopy "Load bookmarks from a bookmark file)")))
+    (define-key map [write]
+      `(menu-item ,(purecopy "Save Bookmarks As...") bookmark-write
+                 :help ,(purecopy "Write bookmarks to a file (reading the file name with the minibuffer)")))
+    (define-key map [save]
+      `(menu-item ,(purecopy "Save Bookmarks") bookmark-save
+                 :help ,(purecopy "Save currently defined bookmarks")))
+    (define-key map [edit]
+      `(menu-item ,(purecopy "Edit Bookmark List") bookmark-bmenu-list
+                 :help ,(purecopy "Display a list of existing bookmarks")))
+    (define-key map [delete]
+      `(menu-item ,(purecopy "Delete Bookmark...") bookmark-delete
+                 :help ,(purecopy "Delete a bookmark from the bookmark list")))
+    (define-key map [rename]
+      `(menu-item ,(purecopy "Rename Bookmark...") bookmark-rename
+                 :help ,(purecopy "Change the name of a bookmark")))
+    (define-key map [locate]
+      `(menu-item ,(purecopy "Insert Location...") bookmark-locate
+                 :help ,(purecopy "Insert the name of the file associated with a bookmark")))
+    (define-key map [insert]
+      `(menu-item ,(purecopy "Insert Contents...") bookmark-insert
+                 :help ,(purecopy "Insert the text of the file pointed to by a bookmark")))
+    (define-key map [set]
+      `(menu-item ,(purecopy "Set Bookmark...") bookmark-set
+                 :help ,(purecopy "Set a bookmark named inside a file.")))
+    (define-key map [jump]
+      `(menu-item ,(purecopy "Jump to Bookmark...") bookmark-jump
+                 :help ,(purecopy "Jump to a bookmark (a point in some file)")))
     map))
 
 ;;;###autoload