diff options
Diffstat (limited to 'lisp/bookmark.el')
-rw-r--r-- | lisp/bookmark.el | 234 |
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 |