diff options
Diffstat (limited to 'lisp/bookmark.el')
-rw-r--r-- | lisp/bookmark.el | 238 |
1 files changed, 146 insertions, 92 deletions
diff --git a/lisp/bookmark.el b/lisp/bookmark.el index cc9956c80a9..c604395dd7d 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -214,31 +214,28 @@ A non-nil value may result in truncated bookmark names." ;;;###autoload (define-key ctl-x-r-map "l" 'bookmark-bmenu-list) ;;;###autoload -(defvar bookmark-map - (let ((map (make-sparse-keymap))) - ;; Read the help on all of these functions for details... - (define-key map "x" 'bookmark-set) - (define-key map "m" 'bookmark-set) ;"m"ark - (define-key map "M" 'bookmark-set-no-overwrite) ;"M"aybe mark - (define-key map "j" 'bookmark-jump) - (define-key map "g" 'bookmark-jump) ;"g"o - (define-key map "o" 'bookmark-jump-other-window) - (define-key map "5" 'bookmark-jump-other-frame) - (define-key map "i" 'bookmark-insert) - (define-key map "e" 'edit-bookmarks) - (define-key map "f" 'bookmark-insert-location) ;"f"ind - (define-key map "r" 'bookmark-rename) - (define-key map "d" 'bookmark-delete) - (define-key map "D" 'bookmark-delete-all) - (define-key map "l" 'bookmark-load) - (define-key map "w" 'bookmark-write) - (define-key map "s" 'bookmark-save) - map) - "Keymap containing bindings to bookmark functions. +(defvar-keymap bookmark-map + :doc "Keymap containing bindings to bookmark functions. It is not bound to any key by default: to bind it so that you have a bookmark prefix, just use `global-set-key' and bind a key of your choice to variable `bookmark-map'. All interactive bookmark -functions have a binding in this keymap.") +functions have a binding in this keymap." + "x" #'bookmark-set + "m" #'bookmark-set ;"m"ark + "M" #'bookmark-set-no-overwrite ;"M"aybe mark + "j" #'bookmark-jump + "g" #'bookmark-jump ;"g"o + "o" #'bookmark-jump-other-window + "5" #'bookmark-jump-other-frame + "i" #'bookmark-insert + "e" #'edit-bookmarks + "f" #'bookmark-insert-location ;"f"ind + "r" #'bookmark-rename + "d" #'bookmark-delete + "D" #'bookmark-delete-all + "l" #'bookmark-load + "w" #'bookmark-write + "s" #'bookmark-save) ;;;###autoload (fset 'bookmark-map bookmark-map) @@ -349,6 +346,17 @@ This point is in `bookmark-current-buffer'.") BOOKMARK-RECORD is, e.g., one element from `bookmark-alist'." (car bookmark-record)) +(defun bookmark-type-from-full-record (bookmark-record) + "Return then type of BOOKMARK-RECORD. +BOOKMARK-RECORD is, e.g., one element from `bookmark-alist'. It's +type is read from the symbol property named +`bookmark-handler-type' read on the record handler function." + (let ((handler (bookmark-get-handler bookmark-record))) + (when (autoloadp (symbol-function handler)) + (autoload-do-load (symbol-function handler))) + (if (symbolp handler) + (get handler 'bookmark-handler-type) + ""))) (defun bookmark-all-names () "Return a list of all current bookmark names." @@ -503,11 +511,8 @@ If DEFAULT is nil then return empty string for empty input." 'string-lessp) (bookmark-all-names))) (let* ((completion-ignore-case bookmark-completion-ignore-case) - (default (unless (equal "" default) default)) - (prompt (concat prompt (if default - (format " (%s): " default) - ": ")))) - (completing-read prompt + (default (unless (equal "" default) default))) + (completing-read (format-prompt prompt default) (lambda (string pred action) (if (eq action 'metadata) '(metadata (category . bookmark)) @@ -518,8 +523,9 @@ If DEFAULT is nil then return empty string for empty input." (defmacro bookmark-maybe-historicize-string (string) "Put STRING into the bookmark prompt history, if caller non-interactive. -We need this because sometimes bookmark functions are invoked from -menus, so `completing-read' never gets a chance to set `bookmark-history'." +We need this because sometimes bookmark functions are invoked +from other commands that pass in the bookmark name, so +`completing-read' never gets a chance to set `bookmark-history'." `(or (called-interactively-p 'interactive) (setq bookmark-history (cons ,string bookmark-history)))) @@ -818,11 +824,9 @@ CODING is the symbol of the coding-system in which the file is encoded." (define-obsolete-function-alias 'bookmark-maybe-message 'message "27.1") -(defvar bookmark-minibuffer-read-name-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map minibuffer-local-map) - (define-key map "\C-w" 'bookmark-yank-word) - map)) +(defvar-keymap bookmark-minibuffer-read-name-map + :parent minibuffer-local-map + "C-w" #'bookmark-yank-word) (defun bookmark-set-internal (prompt name overwrite-or-push) "Set a bookmark using specified NAME or prompting with PROMPT. @@ -926,7 +930,7 @@ it removes only the first instance of a bookmark with that name from the list of bookmarks.)" (interactive (list nil current-prefix-arg)) (let ((prompt - (if no-overwrite "Set bookmark" "Set bookmark unconditionally"))) + (if no-overwrite "Append bookmark named" "Set bookmark named"))) (bookmark-set-internal prompt name (if no-overwrite 'push 'overwrite)))) ;;;###autoload @@ -997,12 +1001,10 @@ annotations." "Function to return default text to use for a bookmark annotation. It takes one argument, the name of the bookmark, as a string.") -(defvar bookmark-edit-annotation-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map text-mode-map) - (define-key map "\C-c\C-c" 'bookmark-send-edited-annotation) - map) - "Keymap for editing an annotation of a bookmark.") +(defvar-keymap bookmark-edit-annotation-mode-map + :doc "Keymap for editing an annotation of a bookmark." + :parent text-mode-map + "C-c C-c" #'bookmark-send-edited-annotation) (defun bookmark-insert-annotation (bookmark-name-or-record) "Insert annotation for BOOKMARK-NAME-OR-RECORD at point." @@ -1287,7 +1289,10 @@ then offer interactively to relocate BOOKMARK-NAME-OR-RECORD." (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'." +Changes current buffer and point and returns nil, or signals a `file-error'. + +If BMK-RECORD has a property called `buffer', it should be a live +buffer object, and this buffer will be selected." (let ((file (bookmark-get-filename bmk-record)) (buf (bookmark-prop-get bmk-record 'buffer)) (forward-str (bookmark-get-front-context-string bmk-record)) @@ -1361,7 +1366,6 @@ minibuffer history list `bookmark-history'." (bookmark-get-filename bookmark-name-or-record) "-- Unknown location --")) - ;;;###autoload (defun bookmark-rename (old-name &optional new-name) "Change the name of OLD-NAME bookmark to NEW-NAME name. @@ -1707,44 +1711,43 @@ unique numeric suffixes \"<2>\", \"<3>\", etc." (defvar bookmark-bmenu-hidden-bookmarks ()) - -(defvar bookmark-bmenu-mode-map - (let ((map (make-keymap))) - (set-keymap-parent map tabulated-list-mode-map) - (define-key map "v" 'bookmark-bmenu-select) - (define-key map "w" 'bookmark-bmenu-locate) - (define-key map "5" 'bookmark-bmenu-other-frame) - (define-key map "2" 'bookmark-bmenu-2-window) - (define-key map "1" 'bookmark-bmenu-1-window) - (define-key map "j" 'bookmark-bmenu-this-window) - (define-key map "\C-c\C-c" 'bookmark-bmenu-this-window) - (define-key map "f" 'bookmark-bmenu-this-window) - (define-key map "\C-m" 'bookmark-bmenu-this-window) - (define-key map "o" 'bookmark-bmenu-other-window) - (define-key map "\C-o" 'bookmark-bmenu-switch-other-window) - (define-key map "s" 'bookmark-bmenu-save) - (define-key map "\C-x\C-s" 'bookmark-bmenu-save) - (define-key map "k" 'bookmark-bmenu-delete) - (define-key map "\C-d" 'bookmark-bmenu-delete-backwards) - (define-key map "x" 'bookmark-bmenu-execute-deletions) - (define-key map "d" 'bookmark-bmenu-delete) - (define-key map "D" 'bookmark-bmenu-delete-all) - (define-key map " " 'next-line) - (define-key map "\177" 'bookmark-bmenu-backup-unmark) - (define-key map "u" 'bookmark-bmenu-unmark) - (define-key map "U" 'bookmark-bmenu-unmark-all) - (define-key map "m" 'bookmark-bmenu-mark) - (define-key map "M" 'bookmark-bmenu-mark-all) - (define-key map "l" 'bookmark-bmenu-load) - (define-key map "r" 'bookmark-bmenu-rename) - (define-key map "R" 'bookmark-bmenu-relocate) - (define-key map "t" 'bookmark-bmenu-toggle-filenames) - (define-key map "a" 'bookmark-bmenu-show-annotation) - (define-key map "A" 'bookmark-bmenu-show-all-annotations) - (define-key map "e" 'bookmark-bmenu-edit-annotation) - (define-key map "/" 'bookmark-bmenu-search) - (define-key map [mouse-2] 'bookmark-bmenu-other-window-with-mouse) - map)) +(defvar-keymap bookmark-bmenu-mode-map + :doc "Keymap for `bookmark-bmenu-mode'." + :parent tabulated-list-mode-map + "v" #'bookmark-bmenu-select + "w" #'bookmark-bmenu-locate + "5" #'bookmark-bmenu-other-frame + "2" #'bookmark-bmenu-2-window + "1" #'bookmark-bmenu-1-window + "j" #'bookmark-bmenu-this-window + "C-c C-c" #'bookmark-bmenu-this-window + "f" #'bookmark-bmenu-this-window + "C-m" #'bookmark-bmenu-this-window + "o" #'bookmark-bmenu-other-window + "C-o" #'bookmark-bmenu-switch-other-window + "s" #'bookmark-bmenu-save + "C-x C-s" #'bookmark-bmenu-save + "k" #'bookmark-bmenu-delete + "C-d" #'bookmark-bmenu-delete-backwards + "x" #'bookmark-bmenu-execute-deletions + "d" #'bookmark-bmenu-delete + "D" #'bookmark-bmenu-delete-all + "S-SPC" #'previous-line + "SPC" #'next-line + "DEL" #'bookmark-bmenu-backup-unmark + "u" #'bookmark-bmenu-unmark + "U" #'bookmark-bmenu-unmark-all + "m" #'bookmark-bmenu-mark + "M" #'bookmark-bmenu-mark-all + "l" #'bookmark-bmenu-load + "r" #'bookmark-bmenu-rename + "R" #'bookmark-bmenu-relocate + "t" #'bookmark-bmenu-toggle-filenames + "a" #'bookmark-bmenu-show-annotation + "A" #'bookmark-bmenu-show-all-annotations + "e" #'bookmark-bmenu-edit-annotation + "/" #'bookmark-bmenu-search + "<mouse-2>" #'bookmark-bmenu-other-window-with-mouse) (easy-menu-define bookmark-menu bookmark-bmenu-mode-map "Menu for `bookmark-bmenu'." @@ -1802,6 +1805,7 @@ Don't affect the buffer ring order." (let (entries) (dolist (full-record (bookmark-maybe-sort-alist)) (let* ((name (bookmark-name-from-full-record full-record)) + (type (bookmark-type-from-full-record full-record)) (annotation (bookmark-get-annotation full-record)) (location (bookmark-location full-record))) (push (list @@ -1815,11 +1819,38 @@ Don't affect the buffer ring order." 'follow-link t 'help-echo "mouse-2: go to this bookmark in other window") name) + ,(or type "") ,@(if bookmark-bmenu-toggle-filenames (list location))]) entries))) - (tabulated-list-init-header) - (setq tabulated-list-entries entries)) + ;; The value of `bookmark-sort-flag' might have changed since the + ;; last time the buffer contents were generated, so re-check it. + (if bookmark-sort-flag + (progn + (setq tabulated-list-sort-key '("Bookmark Name" . nil)) + (setq tabulated-list-entries entries)) + (setq tabulated-list-sort-key nil) + ;; And since we're not sorting by bookmark name, show bookmarks + ;; according to order of creation, with the most recently + ;; created bookmarks at the top and the least recently created + ;; at the bottom. + ;; + ;; Note that clicking the column sort toggle for the bookmark + ;; name column will invoke the `tabulated-list-mode' sort, which + ;; uses `bookmark-bmenu--name-predicate' to sort lexically by + ;; bookmark name instead of by (reverse) creation order. + ;; Clicking the toggle again will reverse the lexical sort, but + ;; the sort will still be lexical not creation-order. However, + ;; if the user reverts the buffer, then the above check of + ;; `bookmark-sort-flag' will happen again and the buffer will + ;; go back to a creation-order sort. This is all expected + ;; behavior, as documented in `bookmark-bmenu-mode'. + (setq tabulated-list-entries (reverse entries))) + ;; Generate the header only after `tabulated-list-sort-key' is + ;; settled, because if that's non-nil then the sort-direction + ;; indicator will be shown in the named column, but if it's + ;; nil then the indicator will not be shown. + (tabulated-list-init-header)) (tabulated-list-print t)) ;;;###autoload @@ -1863,6 +1894,18 @@ deletion, or > if it is flagged for displaying." Each line describes one of the bookmarks in Emacs. Letters do not insert themselves; instead, they are commands. Bookmark names preceded by a \"*\" have annotations. + +If `bookmark-sort-flag' is non-nil, then sort the list by +bookmark name (case-insensitively, in collation order); the +direction of that sort can be reversed by using the column sort +toggle for the bookmark name column. + +If `bookmark-sort-flag' is nil, then sort the list by bookmark +creation order, with most recently created bookmarks on top. +However, the column sort toggle will still activate (and +thereafter toggle the direction of) lexical sorting by bookmark name. +At any time you may use \\[revert-buffer] to go back to sorting by creation order. + \\<bookmark-bmenu-mode-map> \\[bookmark-bmenu-mark] -- mark bookmark to be displayed. \\[bookmark-bmenu-mark-all] -- mark all listed bookmarks to be displayed. @@ -1895,18 +1938,23 @@ Bookmark names preceded by a \"*\" have annotations. in another buffer. \\[bookmark-bmenu-show-all-annotations] -- show the annotations of all bookmarks in another buffer. \\[bookmark-bmenu-edit-annotation] -- edit the annotation for the current bookmark. -\\[bookmark-bmenu-search] -- incrementally search for bookmarks." +\\[bookmark-bmenu-search] -- incrementally search for bookmarks. +\\[revert-buffer] -- refresh the buffer, and thus refresh the sort order (useful + if `bookmark-sort-flag' is nil)." (setq truncate-lines t) (setq buffer-read-only t) ;; FIXME: The header could also display the current default bookmark file ;; according to `bookmark-bookmarks-timestamp'. (setq tabulated-list-format `[("" 1) ;; Space to add "*" for bookmark with annotation - ("Bookmark" ,bookmark-bmenu-file-column bookmark-bmenu--name-predicate) + ("Bookmark Name" + ,bookmark-bmenu-file-column bookmark-bmenu--name-predicate) + ("Type" 8 bookmark-bmenu--type-predicate) ,@(if bookmark-bmenu-toggle-filenames '(("File" 0 bookmark-bmenu--file-predicate)))]) (setq tabulated-list-padding bookmark-bmenu-marks-width) - (setq tabulated-list-sort-key '("Bookmark" . nil)) + (when bookmark-sort-flag + (setq tabulated-list-sort-key '("Bookmark Name" . nil))) (add-hook 'tabulated-list-revert-hook #'bookmark-bmenu--revert nil t)' (setq revert-buffer-function 'bookmark-bmenu--revert) (tabulated-list-init-header)) @@ -1915,13 +1963,19 @@ Bookmark names preceded by a \"*\" have annotations. (defun bookmark-bmenu--name-predicate (a b) "Predicate to sort \"*Bookmark List*\" buffer by the name column. This is used for `tabulated-list-format' in `bookmark-bmenu-mode'." - (string< (caar a) (caar b))) + (string-collate-lessp (caar a) (caar b) nil t)) +(defun bookmark-bmenu--type-predicate (a b) + "Predicate to sort \"*Bookmark List*\" buffer by the type column. +This is used for `tabulated-list-format' in `bookmark-bmenu-mode'." + (string-collate-lessp (elt (cadr a) 2) (elt (cadr b) 2) nil t)) (defun bookmark-bmenu--file-predicate (a b) "Predicate to sort \"*Bookmark List*\" buffer by the file column. This is used for `tabulated-list-format' in `bookmark-bmenu-mode'." - (string< (bookmark-location (car a)) (bookmark-location (car b)))) + (string-collate-lessp (bookmark-location (car a)) + (bookmark-location (car b)) + nil t)) (defun bookmark-bmenu-toggle-filenames (&optional show) @@ -2324,10 +2378,10 @@ Prompt with completion for the new path." (lambda () (setq timer (run-with-idle-timer bookmark-search-delay 'repeat - #'(lambda (buf) - (with-current-buffer buf - (bookmark-bmenu-filter-alist-by-regexp - (minibuffer-contents)))) + (lambda (buf) + (with-current-buffer buf + (bookmark-bmenu-filter-alist-by-regexp + (minibuffer-contents)))) (current-buffer)))) (read-string "Pattern: ") (when timer (cancel-timer timer) (setq timer nil))) |