* net/tramp.el (tramp-get-ls-command)
[bpt/emacs.git] / lisp / bookmark.el
index 38f4478..0eec76f 100644 (file)
@@ -1,7 +1,7 @@
 ;;; bookmark.el --- set bookmarks, maybe annotate them, jump to them later
 
 ;; Copyright (C) 1993, 1994, 1995, 1996, 1997, 2001, 2002, 2003,
-;;   2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+;;   2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Karl Fogel <kfogel@red-bean.com>
 ;; Maintainer: Karl Fogel <kfogel@red-bean.com>
@@ -92,7 +92,7 @@ To specify the file in which to save them, modify the variable
   (if bookmark-file
       ;; In case user set `bookmark-file' in her .emacs:
       bookmark-file
-    (convert-standard-filename "~/.emacs.bmk"))
+    (locate-user-emacs-file "bookmarks" ".emacs.bmk"))
   "File in which to save bookmarks by default."
   :type 'file
   :group 'bookmark)
@@ -528,26 +528,36 @@ old one."
     (setq bookmark-current-bookmark stripped-name)
     (bookmark-bmenu-surreptitiously-rebuild-list)))
 
-(defun bookmark-make-record-default (&optional point-only)
+(defun bookmark-make-record-default (&optional no-file no-context posn)
   "Return the record describing the location of a new bookmark.
-Must be at the correct position in the buffer in which the bookmark is
-being set.
-If POINT-ONLY is non-nil, then only return the subset of the
-record that pertains to the location within the buffer."
-  `(,@(unless point-only `((filename . ,(bookmark-buffer-file-name))))
-    (front-context-string
-     . ,(if (>= (- (point-max) (point)) bookmark-search-size)
-            (buffer-substring-no-properties
-             (point)
-             (+ (point) bookmark-search-size))
-          nil))
-    (rear-context-string
-     . ,(if (>= (- (point) (point-min)) bookmark-search-size)
-            (buffer-substring-no-properties
-             (point)
-             (- (point) bookmark-search-size))
-          nil))
-    (position . ,(point))))
+Point should be at the buffer in which the bookmark is being set,
+and normally should be at the position where the bookmark is desired,
+but see the optional arguments for other possibilities.
+
+If NO-FILE is non-nil, then only return the subset of the
+record that pertains to the location within the buffer, leaving off
+the part that records the filename.
+
+If NO-CONTEXT is non-nil, do not include the front- and rear-context
+strings in the record -- the position is enough.
+
+If POSN is non-nil, record POSN as the point instead of `(point)'."
+  `(,@(unless no-file `((filename . ,(bookmark-buffer-file-name))))
+    ,@(unless no-context `((front-context-string
+                           . ,(if (>= (- (point-max) (point))
+                                      bookmark-search-size)
+                                  (buffer-substring-no-properties
+                                   (point)
+                                   (+ (point) bookmark-search-size))
+                                  nil))))
+    ,@(unless no-context `((rear-context-string
+                           . ,(if (>= (- (point) (point-min))
+                                      bookmark-search-size)
+                                  (buffer-substring-no-properties
+                                   (point)
+                                   (- (point) bookmark-search-size))
+                                  nil))))
+    (position . ,(or posn (point)))))
 
 \f
 ;;; File format stuff
@@ -773,27 +783,34 @@ 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 (list nil current-prefix-arg))
-  (let* ((record (bookmark-make-record))
-         (default (car record)))
+  (unwind-protect
+       (let* ((record (bookmark-make-record))
+              (default (car record)))
+
+         (bookmark-maybe-load-default-file)
+         ;; Don't set `bookmark-yank-point' and `bookmark-current-buffer'
+         ;; if they have been already set in another buffer. (e.g gnus-art).
+         (unless (and bookmark-yank-point
+                      bookmark-current-buffer)
+           (setq bookmark-yank-point (point))
+           (setq bookmark-current-buffer (current-buffer)))
+
+         (let ((str
+                (or name
+                    (read-from-minibuffer
+                     (format "Set bookmark (%s): " default)
+                     nil
+                     bookmark-minibuffer-read-name-map
+                     nil nil default))))
+           (and (string-equal str "") (setq str default))
+           (bookmark-store str (cdr record) no-overwrite)
+
+           ;; Ask for an annotation buffer for this bookmark
+           (when bookmark-use-annotations
+             (bookmark-edit-annotation str))))
+    (setq bookmark-yank-point nil)
+    (setq bookmark-current-buffer nil)))
 
-    (bookmark-maybe-load-default-file)
-
-    (setq bookmark-yank-point (point))
-    (setq bookmark-current-buffer (current-buffer))
-
-    (let ((str
-           (or name
-               (read-from-minibuffer
-                (format "Set bookmark (%s): " default)
-                nil
-                bookmark-minibuffer-read-name-map
-                nil nil default))))
-      (and (string-equal str "") (setq str default))
-      (bookmark-store str (cdr record) no-overwrite)
-
-      ;; Ask for an annotation buffer for this bookmark
-      (when bookmark-use-annotations
-        (bookmark-edit-annotation str)))))
 
 (defun bookmark-kill-line (&optional newline-too)
   "Kill from point to end of line.
@@ -958,14 +975,14 @@ it to the name of the bookmark currently being set, advancing
            (and
             ;; Possibly the old bookmark file, "~/.emacs-bkmrks", needs
             ;; to be renamed.
-            (file-exists-p (expand-file-name bookmark-old-default-file))
-            (not (file-exists-p (expand-file-name bookmark-default-file)))
-            (rename-file (expand-file-name bookmark-old-default-file)
-                         (expand-file-name bookmark-default-file)))
+            (file-exists-p bookmark-old-default-file)
+            (not (file-exists-p bookmark-default-file))
+            (rename-file bookmark-old-default-file
+                         bookmark-default-file))
            ;; return t so the `and' will continue...
            t)
 
-       (file-readable-p (expand-file-name bookmark-default-file))
+       (file-readable-p bookmark-default-file)
        (bookmark-load bookmark-default-file t t)
        (setq bookmarks-already-loaded t)))
 
@@ -1068,7 +1085,7 @@ that file no longer exists, then offer interactively to relocate BOOKMARK."
       (funcall (or (bookmark-get-handler bookmark)
                    'bookmark-default-handler)
                (bookmark-get-bookmark bookmark))
-    (file-error
+    (bookmark-error-no-filename         ;file-error
      ;; 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)
@@ -1116,24 +1133,28 @@ that file no longer exists, then offer interactively to relocate BOOKMARK."
 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)))
-    (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
-      ;; 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)
-              (goto-char (match-beginning 0))))
-      (if behind-str
-          (if (search-backward behind-str (point-min) t)
-              (goto-char (match-end 0)))))
+    (set-buffer
+     (cond
+      ((and file (file-readable-p file) (not (buffer-live-p buf)))
+       (find-file-noselect file))
+      ;; No file found.  See if buffer BUF have been created.
+      ((and buf (get-buffer buf)))
+      (t ;; If not, raise error.
+       (signal 'bookmark-error-no-filename (list 'stringp 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
+    ;; file, it's better to be put before it so you can read it,
+    ;; rather than after and remain perhaps unaware of the changes.
+    (when (and forward-str (search-forward forward-str (point-max) t))
+      (goto-char (match-beginning 0)))
+    (when (and behind-str (search-backward behind-str (point-min) t))
+      (goto-char (match-end 0)))
     nil))
 
 ;;;###autoload
@@ -1148,10 +1169,11 @@ after a bookmark was set in it."
   (bookmark-maybe-historicize-string bookmark)
   (bookmark-maybe-load-default-file)
   (let* ((bmrk-filename (bookmark-get-filename bookmark))
-         (newloc (expand-file-name
-                  (read-file-name
-                   (format "Relocate %s to: " bookmark)
-                   (file-name-directory bmrk-filename)))))
+         (newloc (abbreviate-file-name
+                  (expand-file-name
+                   (read-file-name
+                    (format "Relocate %s to: " bookmark)
+                    (file-name-directory bmrk-filename))))))
     (bookmark-set-filename bookmark newloc)
     (setq bookmark-alist-modification-count
           (1+ bookmark-alist-modification-count))
@@ -1171,7 +1193,7 @@ minibuffer history list `bookmark-history'."
   (or no-history (bookmark-maybe-historicize-string bookmark))
   (let ((start (point)))
     (prog1
-       (insert (bookmark-location bookmark)) ; *Return this line*
+       (insert (bookmark-location bookmark))
       (if (display-mouse-p)
          (add-text-properties
           start
@@ -1186,10 +1208,16 @@ minibuffer history list `bookmark-history'."
 (defalias 'bookmark-locate 'bookmark-insert-location)
 
 (defun bookmark-location (bookmark)
-  "Return the name of the file associated with BOOKMARK, or nil if none.
+  "Return a description of the location of BOOKMARK.
 BOOKMARK may be a bookmark name (a string) or a bookmark record."
   (bookmark-maybe-load-default-file)
-  (bookmark-get-filename bookmark))
+  ;; We could call the `handler' and ask for it to construct a description
+  ;; dynamically: it would open up several new possibilities, but it
+  ;; would have the major disadvantage of forcing to load each and
+  ;; every handler when the user calls bookmark-menu.
+  (or (bookmark-prop-get bookmark 'location)
+      (bookmark-get-filename bookmark)
+      "-- Unknown location --"))
 
 
 ;;;###autoload
@@ -1428,7 +1456,7 @@ method buffers use to resolve name collisions."
           ;;but there's no better default, and
           ;;I guess it's better than none at all.
           "~/" bookmark-default-file 'confirm)))
-  (setq file (expand-file-name file))
+  (setq file (abbreviate-file-name (expand-file-name file)))
   (if (not (file-readable-p file))
       (error "Cannot read bookmark file %s" file)
     (if (null no-msg)
@@ -1449,7 +1477,8 @@ method buffers use to resolve name collisions."
                 (setq bookmark-alist-modification-count
                       (1+ bookmark-alist-modification-count)))
               (if (string-equal
-                   (expand-file-name bookmark-default-file)
+                   (abbreviate-file-name
+                    (expand-file-name bookmark-default-file))
                    file)
                   (setq bookmarks-already-loaded t))
               (bookmark-bmenu-surreptitiously-rebuild-list))
@@ -1721,15 +1750,15 @@ last full line, move to the last full line.  The return value is undefined."
   "Display the annotation for bookmark named BOOKMARK in a buffer,
 if an annotation exists."
   (let ((annotation (bookmark-get-annotation bookmark)))
-    (if (and annotation (not (string-equal annotation "")))
-        (save-excursion
-          (let ((old-buf (current-buffer)))
-            (pop-to-buffer (get-buffer-create "*Bookmark Annotation*") t)
-            (delete-region (point-min) (point-max))
-            ;; (insert (concat "Annotation for bookmark '" bookmark "':\n\n"))
-            (insert annotation)
-            (goto-char (point-min))
-            (pop-to-buffer old-buf))))))
+    (when (and annotation (not (string-equal annotation "")))
+      (save-excursion
+        (let ((old-buf (current-buffer)))
+          (pop-to-buffer (get-buffer-create "*Bookmark Annotation*") t)
+          (delete-region (point-min) (point-max))
+          ;; (insert (concat "Annotation for bookmark '" bookmark "':\n\n"))
+          (insert annotation)
+          (goto-char (point-min))
+          (switch-to-buffer-other-window old-buf))))))
 
 
 (defun bookmark-show-all-annotations ()
@@ -1848,8 +1877,7 @@ With a prefix arg, prompts for a file to save them in."
         (pop-up-windows t))
     (delete-other-windows)
     (switch-to-buffer (other-buffer))
-    (let ((bookmark-automatically-show-annotations nil)) ;FIXME: needed?
-      (bookmark--jump-via bmrk 'pop-to-buffer))
+    (bookmark--jump-via bmrk 'pop-to-buffer)
     (bury-buffer menu)))
 
 
@@ -1863,8 +1891,7 @@ With a prefix arg, prompts for a file to save them in."
   "Select this line's bookmark in other window, leaving bookmark menu visible."
   (interactive)
   (let ((bookmark (bookmark-bmenu-bookmark)))
-    (let ((bookmark-automatically-show-annotations t)) ;FIXME: needed?
-      (bookmark--jump-via bookmark 'switch-to-buffer-other-window))))
+    (bookmark--jump-via bookmark 'switch-to-buffer-other-window)))
 
 
 (defun bookmark-bmenu-switch-other-window ()
@@ -1875,8 +1902,7 @@ The current window remains selected."
         (pop-up-windows t)
         same-window-buffer-names
         same-window-regexps)
-    (let ((bookmark-automatically-show-annotations t)) ;FIXME: needed?
-      (bookmark--jump-via bookmark 'display-buffer))))
+    (bookmark--jump-via bookmark 'display-buffer)))
 
 (defun bookmark-bmenu-other-window-with-mouse (event)
   "Select bookmark at the mouse pointer in other window, leaving bookmark menu visible."
@@ -1960,7 +1986,7 @@ To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\
 
 
 (defun bookmark-bmenu-execute-deletions ()
-  "Delete bookmarks marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-delete] commands."
+  "Delete bookmarks flagged `D'."
   (interactive)
   (message "Deleting bookmarks...")
   (let ((o-point  (point))
@@ -2170,7 +2196,7 @@ strings returned are not."
 \f
 ;; Load Hook
 (defvar bookmark-load-hook nil
-  "Hook run at the end of loading bookmark.")
+  "Hook run at the end of loading library `bookmark.el'.")
 
 ;; Exit Hook, called from kill-emacs-hook
 (defvar bookmark-exit-hook nil