;;; 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>
(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)
(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
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.
(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)))
(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)
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
(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))
(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
(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
;;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)
(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))
"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 ()
(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)))
"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 ()
(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."
(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))
\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