summaryrefslogtreecommitdiff
path: root/lisp/bookmark.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/bookmark.el')
-rw-r--r--lisp/bookmark.el234
1 files changed, 169 insertions, 65 deletions
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index dcf8ff0d0af..ff9b8ab1388 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -121,6 +121,12 @@ recently set ones come first, oldest ones come last)."
:type 'boolean)
+(defcustom bookmark-menu-confirm-deletion nil
+ "Non-nil means confirm before deleting bookmarks in a bookmark menu buffer.
+Nil means don't prompt for confirmation."
+ :version "28.1"
+ :type 'boolean)
+
(defcustom bookmark-automatically-show-annotations t
"Non-nil means show annotations when jumping to a bookmark."
:type 'boolean)
@@ -167,12 +173,34 @@ A non-nil value may result in truncated bookmark names."
"Time before `bookmark-bmenu-search' updates the display."
:type 'number)
+(defcustom bookmark-fontify t
+ "Whether to colorize a bookmarked line.
+If non-nil, setting a bookmark will colorize the current line with
+`bookmark-face'."
+ :type 'boolean
+ :version "28.1")
+
;; FIXME: No longer used. Should be declared obsolete or removed.
(defface bookmark-menu-heading
'((t (:inherit font-lock-type-face)))
"Face used to highlight the heading in bookmark menu buffers."
:version "22.1")
+(defface bookmark-face
+ '((((class grayscale)
+ (background light))
+ :background "DimGray")
+ (((class grayscale)
+ (background dark))
+ :background "LightGray")
+ (((class color)
+ (background light))
+ :foreground "White" :background "DarkOrange1")
+ (((class color)
+ (background dark))
+ :foreground "Black" :background "DarkOrange1"))
+ "Face used to highlight current line."
+ :version "28.1")
;;; No user-serviceable parts beyond this point.
@@ -427,6 +455,30 @@ In other words, return all information but the name."
(defvar bookmark-history nil
"The history list for bookmark functions.")
+(defun bookmark--fontify ()
+ "Apply a colorized overlay to the bookmarked location.
+See user option `bookmark-fontify'."
+ (let ((bm (make-overlay (point-at-bol)
+ (min (point-max) (1+ (point-at-eol))))))
+ (overlay-put bm 'category 'bookmark)
+ (overlay-put bm 'face 'bookmark-face)))
+
+(defun bookmark--unfontify (bm)
+ "Remove a bookmark's colorized overlay.
+BM is a bookmark as returned from function `bookmark-get-bookmark'.
+See user option `bookmark-fontify'."
+ (let ((filename (cdr (assq 'filename bm)))
+ (pos (cdr (assq 'position bm)))
+ overlays found temp)
+ (when (and pos filename)
+ (setq filename (expand-file-name filename))
+ (dolist (buf (buffer-list))
+ (with-current-buffer buf
+ (when (equal filename buffer-file-name)
+ (setq overlays (overlays-at pos))
+ (while (and (not found) (setq temp (pop overlays)))
+ (when (eq 'bookmark (overlay-get temp 'category))
+ (delete-overlay (setq found temp))))))))))
(defun bookmark-completing-read (prompt &optional default)
"Prompting with PROMPT, read a bookmark name in completion.
@@ -509,10 +561,14 @@ old one."
(set-text-properties 0 (length stripped-name) nil stripped-name)
(if (and (not no-overwrite)
(bookmark-get-bookmark stripped-name 'noerror))
- ;; already existing bookmark under that name and
- ;; no prefix arg means just overwrite old bookmark
- ;; Use the new (NAME . ALIST) format.
- (setcdr (bookmark-get-bookmark stripped-name) alist)
+ ;; Already existing bookmark under that name and
+ ;; no prefix arg means just overwrite old bookmark.
+ (let ((bm (bookmark-get-bookmark stripped-name)))
+ ;; First clean up if previously location was fontified.
+ (when bookmark-fontify
+ (bookmark--unfontify bm))
+ ;; Modify using the new (NAME . ALIST) format.
+ (setcdr bm alist))
;; otherwise just cons it onto the front (either the bookmark
;; doesn't exist already, or there is no prefix arg. In either
@@ -825,7 +881,9 @@ still there, in order, if the topmost one is ever deleted."
;; Ask for an annotation buffer for this bookmark
(when bookmark-use-annotations
- (bookmark-edit-annotation str))))
+ (bookmark-edit-annotation str))
+ (when bookmark-fontify
+ (bookmark--fontify))))
(setq bookmark-yank-point nil)
(setq bookmark-current-buffer nil)))
@@ -953,7 +1011,7 @@ When you have finished composing, type \\[bookmark-send-edited-annotation].
(defun bookmark-send-edited-annotation ()
"Use buffer contents as annotation for a bookmark.
Lines beginning with `#' are ignored."
- (interactive)
+ (interactive nil bookmark-edit-annotation-mode)
(if (not (derived-mode-p 'bookmark-edit-annotation-mode))
(error "Not in bookmark-edit-annotation-mode"))
(goto-char (point-min))
@@ -1040,6 +1098,14 @@ it to the name of the bookmark currently being set, advancing
(car dired-directory)))
(t (error "Buffer not visiting a file or directory")))))
+(defvar bookmark--watch-already-asked-mtime nil
+ "Mtime for which we already queried about reloading.")
+
+(defun bookmark--watch-file-already-queried-p (new-mtime)
+ ;; Don't ask repeatedly if user already said "no" to reloading a
+ ;; file with this mtime:
+ (prog1 (equal new-mtime bookmark--watch-already-asked-mtime)
+ (setq bookmark--watch-already-asked-mtime new-mtime)))
(defun bookmark-maybe-load-default-file ()
"If bookmarks have not been loaded from the default place, load them."
@@ -1048,13 +1114,15 @@ it to the name of the bookmark currently being set, advancing
(file-readable-p bookmark-default-file)
(bookmark-load bookmark-default-file t t)))
((and bookmark-watch-bookmark-file
- (not (equal (nth 5 (file-attributes
- (car bookmark-bookmarks-timestamp)))
- (cdr bookmark-bookmarks-timestamp)))
- (or (eq 'silent bookmark-watch-bookmark-file)
- (yes-or-no-p
- (format "Bookmarks %s changed on disk. Reload? "
- (car bookmark-bookmarks-timestamp)))))
+ (let ((new-mtime (nth 5 (file-attributes
+ (car bookmark-bookmarks-timestamp))))
+ (old-mtime (cdr bookmark-bookmarks-timestamp)))
+ (and (not (equal new-mtime old-mtime))
+ (not (bookmark--watch-file-already-queried-p new-mtime))
+ (or (eq 'silent bookmark-watch-bookmark-file)
+ (yes-or-no-p
+ (format "Bookmarks %s changed on disk. Reload? "
+ (car bookmark-bookmarks-timestamp)))))))
(bookmark-load (car bookmark-bookmarks-timestamp) t t))))
(defun bookmark-maybe-sort-alist ()
@@ -1084,6 +1152,14 @@ and then show any annotations for this bookmark."
(if win (set-window-point win (point))))
;; FIXME: we used to only run bookmark-after-jump-hook in
;; `bookmark-jump' itself, but in none of the other commands.
+ (when bookmark-fontify
+ (let ((overlays (overlays-at (point)))
+ temp found)
+ (while (and (not found) (setq temp (pop overlays)))
+ (when (eq 'bookmark (overlay-get temp 'category))
+ (setq found t)))
+ (unless found
+ (bookmark--fontify))))
(run-hooks 'bookmark-after-jump-hook)
(if bookmark-automatically-show-annotations
;; if there is an annotation for this bookmark,
@@ -1347,6 +1423,7 @@ probably because we were called from there."
(bookmark-maybe-historicize-string bookmark-name)
(bookmark-maybe-load-default-file)
(let ((will-go (bookmark-get-bookmark bookmark-name 'noerror)))
+ (bookmark--unfontify will-go)
(setq bookmark-alist (delq will-go bookmark-alist))
;; Added by db, nil bookmark-current-bookmark if the last
;; occurrence has been deleted
@@ -1366,6 +1443,13 @@ probably because we were called from there."
If optional argument NO-CONFIRM is non-nil, don't ask for
confirmation."
(interactive "P")
+ ;; We don't use `bookmark-menu-confirm-deletion' here because that
+ ;; variable is specifically to control confirmation prompting in a
+ ;; bookmark menu buffer, where the user has the marked-for-deletion
+ ;; bookmarks arrayed in front of them and might have accidentally
+ ;; hit the key that executes the deletions. The UI situation here
+ ;; is quite different, by contrast: the user got to this point by a
+ ;; sequence of keystrokes unlikely to be typed by chance.
(when (or no-confirm
(yes-or-no-p "Permanently delete all bookmarks? "))
(bookmark-maybe-load-default-file)
@@ -1827,7 +1911,7 @@ This is used for `tabulated-list-format' in `bookmark-bmenu-mode'."
(defun bookmark-bmenu-toggle-filenames (&optional show)
"Toggle whether filenames are shown in the bookmark list.
Optional argument SHOW means show them unconditionally."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(cond
(show
(setq bookmark-bmenu-toggle-filenames t))
@@ -1912,14 +1996,14 @@ If the annotation does not exist, do nothing."
(defun bookmark-bmenu-mark ()
"Mark bookmark on this line to be displayed by \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-select]."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(bookmark-bmenu-ensure-position)
(tabulated-list-put-tag ">" t))
(defun bookmark-bmenu-mark-all ()
"Mark all listed bookmarks to be displayed by \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-select]."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(save-excursion
(goto-char (point-min))
(bookmark-bmenu-ensure-position)
@@ -1930,7 +2014,7 @@ If the annotation does not exist, do nothing."
(defun bookmark-bmenu-select ()
"Select this line's bookmark; also display bookmarks marked with `>'.
You can mark bookmarks with the \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mark] or \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mark-all] commands."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bmrk (bookmark-bmenu-bookmark))
(menu (current-buffer))
(others ())
@@ -1974,8 +2058,11 @@ You can mark bookmarks with the \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mar
(defun bookmark-bmenu-save ()
"Save the current list into a bookmark file.
-With a prefix arg, prompts for a file to save them in."
- (interactive)
+With a prefix arg, prompts for a file to save them in.
+
+See also the related behaviors of `bookmark-load' and
+`bookmark-bmenu-load'."
+ (interactive nil bookmark-bmenu-mode)
(save-excursion
(save-window-excursion
(call-interactively 'bookmark-save)
@@ -1983,8 +2070,20 @@ With a prefix arg, prompts for a file to save them in."
(defun bookmark-bmenu-load ()
- "Load the bookmark file and rebuild the bookmark menu-buffer."
- (interactive)
+ "Load bookmarks from a file and rebuild the bookmark menu-buffer.
+Prompt for a file, with the default choice being the value of
+`bookmark-default-file'.
+
+With a prefix argument, replace the current ambient bookmarks
+(i.e., the ones in `bookmark-alist') with the ones from the selected
+file and make that file be the new value of `bookmark-default-file'.
+In other words, a prefix argument means \"switch over to the bookmark
+universe defined in the loaded file\". Without a prefix argument,
+just add the loaded bookmarks into the current ambient set.
+
+See the documentation for `bookmark-load' for more details; see also
+the related behaviors of `bookmark-save' and `bookmark-bmenu-save'."
+ (interactive nil bookmark-bmenu-mode)
(bookmark-bmenu-ensure-position)
(save-excursion
(save-window-excursion
@@ -1994,7 +2093,7 @@ With a prefix arg, prompts for a file to save them in."
(defun bookmark-bmenu-1-window ()
"Select this line's bookmark, alone, in full frame."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(bookmark-jump (bookmark-bmenu-bookmark))
(bury-buffer (other-buffer))
(delete-other-windows))
@@ -2002,7 +2101,7 @@ With a prefix arg, prompts for a file to save them in."
(defun bookmark-bmenu-2-window ()
"Select this line's bookmark, with previous buffer in second window."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bmrk (bookmark-bmenu-bookmark))
(menu (current-buffer))
(pop-up-windows t))
@@ -2014,20 +2113,20 @@ With a prefix arg, prompts for a file to save them in."
(defun bookmark-bmenu-this-window ()
"Select this line's bookmark in this window."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(bookmark-jump (bookmark-bmenu-bookmark)))
(defun bookmark-bmenu-other-window ()
"Select this line's bookmark in other window, leaving bookmark menu visible."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bookmark (bookmark-bmenu-bookmark)))
(bookmark--jump-via bookmark 'switch-to-buffer-other-window)))
(defun bookmark-bmenu-other-frame ()
"Select this line's bookmark in other frame."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bookmark (bookmark-bmenu-bookmark))
(pop-up-frames t))
(bookmark-jump-other-window bookmark)))
@@ -2035,7 +2134,7 @@ With a prefix arg, prompts for a file to save them in."
(defun bookmark-bmenu-switch-other-window ()
"Make the other window select this line's bookmark.
The current window remains selected."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bookmark (bookmark-bmenu-bookmark))
(fun (lambda (b) (display-buffer b t))))
(bookmark--jump-via bookmark fun)))
@@ -2044,7 +2143,7 @@ The current window remains selected."
"Jump to bookmark at mouse EVENT position in other window.
Move point in menu buffer to the position of EVENT and leave
bookmark menu visible."
- (interactive "e")
+ (interactive "e" bookmark-bmenu-mode)
(with-current-buffer (window-buffer (posn-window (event-end event)))
(save-excursion
(goto-char (posn-point (event-end event)))
@@ -2053,20 +2152,20 @@ bookmark menu visible."
(defun bookmark-bmenu-show-annotation ()
"Show the annotation for the current bookmark in another window."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bookmark (bookmark-bmenu-bookmark)))
(bookmark-show-annotation bookmark)))
(defun bookmark-bmenu-show-all-annotations ()
"Show the annotation for all bookmarks in another window."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(bookmark-show-all-annotations))
(defun bookmark-bmenu-edit-annotation ()
"Edit the annotation for the current bookmark in another window."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bookmark (bookmark-bmenu-bookmark)))
(bookmark-edit-annotation bookmark t)))
@@ -2074,7 +2173,7 @@ bookmark menu visible."
(defun bookmark-bmenu-unmark (&optional backup)
"Cancel all requested operations on bookmark on this line and move down.
Optional BACKUP means move up."
- (interactive "P")
+ (interactive "P" bookmark-bmenu-mode)
;; any flags to reset according to circumstances? How about a
;; flag indicating whether this bookmark is being visited?
;; well, we don't have this now, so maybe later.
@@ -2085,7 +2184,7 @@ Optional BACKUP means move up."
(defun bookmark-bmenu-backup-unmark ()
"Move up and cancel all requested operations on bookmark on line above."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(forward-line -1)
(bookmark-bmenu-ensure-position)
(bookmark-bmenu-unmark)
@@ -2095,7 +2194,7 @@ Optional BACKUP means move up."
(defun bookmark-bmenu-unmark-all ()
"Cancel all requested operations on all listed bookmarks."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(save-excursion
(goto-char (point-min))
(bookmark-bmenu-ensure-position)
@@ -2106,7 +2205,7 @@ Optional BACKUP means move up."
(defun bookmark-bmenu-delete ()
"Mark bookmark on this line to be deleted.
To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(bookmark-bmenu-ensure-position)
(tabulated-list-put-tag "D" t))
@@ -2114,7 +2213,7 @@ To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\
(defun bookmark-bmenu-delete-backwards ()
"Mark bookmark on this line to be deleted, then move up one line.
To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(bookmark-bmenu-delete)
(forward-line -2))
@@ -2123,7 +2222,7 @@ To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\
"Mark all listed bookmarks as to be deleted.
To remove all deletion marks, use \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-unmark-all].
To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(save-excursion
(goto-char (point-min))
(bookmark-bmenu-ensure-position)
@@ -2132,35 +2231,40 @@ To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\
(defun bookmark-bmenu-execute-deletions ()
- "Delete bookmarks flagged `D'."
- (interactive)
- (let ((reporter (make-progress-reporter "Deleting bookmarks..."))
- (o-point (point))
- (o-str (save-excursion
- (beginning-of-line)
- (unless (= (following-char) ?D)
- (buffer-substring
- (point)
- (progn (end-of-line) (point))))))
- (o-col (current-column)))
- (goto-char (point-min))
- (while (re-search-forward "^D" (point-max) t)
- (bookmark-delete (bookmark-bmenu-bookmark) t)) ; pass BATCH arg
- (bookmark-bmenu-list)
- (if o-str
- (progn
- (goto-char (point-min))
- (search-forward o-str)
- (beginning-of-line)
- (forward-char o-col))
- (goto-char o-point))
- (beginning-of-line)
- (progress-reporter-done reporter)))
+ "Delete bookmarks flagged `D'.
+If `bookmark-menu-confirm-deletion' is non-nil, prompt for
+confirmation first."
+ (interactive nil bookmark-bmenu-mode)
+ (if (and bookmark-menu-confirm-deletion
+ (not (yes-or-no-p "Delete selected bookmarks? ")))
+ (message "Bookmarks not deleted.")
+ (let ((reporter (make-progress-reporter "Deleting bookmarks..."))
+ (o-point (point))
+ (o-str (save-excursion
+ (beginning-of-line)
+ (unless (= (following-char) ?D)
+ (buffer-substring
+ (point)
+ (progn (end-of-line) (point))))))
+ (o-col (current-column)))
+ (goto-char (point-min))
+ (while (re-search-forward "^D" (point-max) t)
+ (bookmark-delete (bookmark-bmenu-bookmark) t)) ; pass BATCH arg
+ (bookmark-bmenu-list)
+ (if o-str
+ (progn
+ (goto-char (point-min))
+ (search-forward o-str)
+ (beginning-of-line)
+ (forward-char o-col))
+ (goto-char o-point))
+ (beginning-of-line)
+ (progress-reporter-done reporter))))
(defun bookmark-bmenu-rename ()
"Rename bookmark on current line. Prompts for a new name."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bmrk (bookmark-bmenu-bookmark))
(thispoint (point)))
(bookmark-rename bmrk)
@@ -2169,14 +2273,14 @@ To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\
(defun bookmark-bmenu-locate ()
"Display location of this bookmark. Displays in the minibuffer."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bmrk (bookmark-bmenu-bookmark)))
(message "%s" (bookmark-location bmrk))))
(defun bookmark-bmenu-relocate ()
"Change the absolute file name of the bookmark on the current line.
Prompt with completion for the new path."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bmrk (bookmark-bmenu-bookmark))
(thispoint (point)))
(bookmark-relocate bmrk)
@@ -2196,7 +2300,7 @@ Prompt with completion for the new path."
;;;###autoload
(defun bookmark-bmenu-search ()
"Incremental search of bookmarks, hiding the non-matches as we go."
- (interactive)
+ (interactive nil bookmark-bmenu-mode)
(let ((bmk (bookmark-bmenu-bookmark))
(timer nil))
(unwind-protect