(define-key calendar-mode-map (kbd "RET") 'calendar-insert-date)
#+end_src
+
+* [[https://www.emacswiki.org/emacs/BookmarkPlus][Bookmark+]]
+[2022-02-10 Thu 15:22]
+
+#+BEGIN_SRC emacs-lisp
+ (if (equal "work" (getenv "SYSENV"))
+ (setq bookmark-default-file "~/workorg/bookmarks")
+ (setq bookmark-default-file "~/org/bookmarks"))
+ (load-file (expand-file-name "~/.emacs.d/lisp/bookmark+.el"))
+ (load-file (expand-file-name "~/.emacs.d/lisp/bookmark+-mac.el"))
+ (load-file (expand-file-name "~/.emacs.d/lisp/bookmark+-bmu.el"))
+ (load-file (expand-file-name "~/.emacs.d/lisp/bookmark+-1.el"))
+ (load-file (expand-file-name "~/.emacs.d/lisp/bookmark+-key.el"))
+ (load-file (expand-file-name "~/.emacs.d/lisp/bookmark+-lit.el"))
+
+#+END_SRC
+
* magit
For annotated tags prepare message with commit messages since last tag.
--- /dev/null
+;;; bookmark+-1.el - First part of package Bookmark+.
+;;
+;; Filename: bookmark+-1.el
+;; Description: First part of package Bookmark+.
+;; Author: Drew Adams, Thierry Volpiatto
+;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com")
+;; Copyright (C) 2000-2022, Drew Adams, all rights reserved.
+;; Copyright (C) 2009, Thierry Volpiatto.
+;; Created: Mon Jul 12 13:43:55 2010 (-0700)
+;; Last-Updated: Fri Jan 14 12:34:36 2022 (-0800)
+;; By: dradams
+;; Update #: 9453
+;; URL: https://www.emacswiki.org/emacs/download/bookmark%2b-1.el
+;; Doc URL: https://www.emacswiki.org/emacs/BookmarkPlus
+;; Keywords: bookmarks, bookmark+, placeholders, annotations, search, info, url, eww, w3m, gnus
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x, 26.x
+;;
+;; Features that might be required by this library:
+;;
+;; `backquote', `bookmark', `bookmark+-1', `button', `bytecomp',
+;; `cconv', `cl-lib', `col-highlight', `crosshairs', `font-lock',
+;; `font-lock+', `help-mode', `hl-line', `hl-line+', `kmacro',
+;; `macroexp', `pp', `replace', `syntax', `text-mode', `thingatpt',
+;; `thingatpt+', `vline'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; The Bookmark+ libraries are these:
+;;
+;; `bookmark+.el' - main (driver) library
+;; `bookmark+-mac.el' - Lisp macros
+;; `bookmark+-lit.el' - (optional) code for highlighting bookmarks
+;; `bookmark+-bmu.el' - code for the `*Bookmark List*' (bmenu)
+;; `bookmark+-1.el' - other (non-bmenu) required code (this file)
+;; `bookmark+-key.el' - key and menu bindings
+;;
+;; `bookmark+-doc.el' - documentation (comment-only file)
+;; `bookmark+-chg.el' - change log (comment-only file)
+;;
+;; The documentation (in `bookmark+-doc.el') includes how to
+;; byte-compile and install Bookmark+. The documentation is also
+;; available in these ways:
+;;
+;; 1. From the bookmark list (`C-x r l'):
+;; Use `?' to show the current bookmark-list status and general
+;; help, then click link `Doc in Commentary' or link `Doc on the
+;; Web'.
+;;
+;; 2. From the Emacs-Wiki Web site:
+;; https://www.emacswiki.org/emacs/BookmarkPlus.
+;;
+;; 3. From the Bookmark+ group customization buffer:
+;; `M-x customize-group bookmark-plus', then click link
+;; `Commentary'.
+;;
+;; (The commentary links in #1 and #3 work only if you have library
+;; `bookmark+-doc.el' in your `load-path'.)
+
+;;(@> "Index")
+;;
+;; Index
+;; -----
+;;
+;; If you have library `linkd.el' and Emacs 22 or later, load
+;; `linkd.el' and turn on `linkd-mode' now. It lets you easily
+;; navigate around the sections of this doc. Linkd mode will
+;; highlight this Index, as well as the cross-references and section
+;; headings throughout this file. You can get `linkd.el' here:
+;; https://www.emacswiki.org/emacs/download/linkd.el.
+;;
+;; (@> "Things Defined Here")
+;; (@> "User Options (Customizable)")
+;; (@> "Internal Variables")
+;; (@> "Compatibility Code for Older Emacs Versions")
+;; (@> "Core Replacements (`bookmark-*' except `bookmark-bmenu-*')")
+;; (@> "Bookmark+ Functions (`bmkp-*')")
+;; (@> "Search-and-Replace Locations of Marked Bookmarks")
+;; (@> "Tags")
+;; (@> "Bookmark Predicates")
+;; (@> "Filter Functions")
+;; (@> "General Utility Functions")
+;; (@> "Bookmark Entry Access Functions")
+;; (@> "Sorting - General Functions")
+;; (@> "Sorting - Commands")
+;; (@> "Sorting - General Predicates")
+;; (@> "Sorting - File-Name Predicates")
+;; (@> "Indirect Bookmarking Functions")
+;; (@> "Other Bookmark+ Functions (`bmkp-*')")
+;; (@> "Keymaps")
+
+;;(@* "Things Defined Here")
+;;
+;; Things Defined Here
+;; -------------------
+;;
+;; Commands defined here:
+;;
+;; `bmkp-add-tags', `bmkp-all-tags-jump',
+;; `bmkp-all-tags-jump-other-window', `bmkp-all-tags-regexp-jump',
+;; `bmkp-all-tags-regexp-jump-other-window',
+;; `bmkp-annotate-all-bookmarks-this-file/buffer',
+;; `bmkp-annotate-bookmark',
+;; `bmkp-annotate-bookmark-this-file/buffer',
+;; `bmkp-autofile-add-tags', `bmkp-autofile-all-tags-jump',
+;; `bmkp-autofile-all-tags-jump-other-window',
+;; `bmkp-autofile-all-tags-regexp-jump',
+;; `bmkp-autofile-all-tags-regexp-jump-other-window',
+;; `bmkp-autofile-jump', `bmkp-autofile-jump-other-window',
+;; `bmkp-autofile-remove-tags', `bmkp-autofile-set',
+;; `bmkp-autofile-some-tags-jump',
+;; `bmkp-autofile-some-tags-jump-other-window',
+;; `bmkp-autofile-some-tags-regexp-jump',
+;; `bmkp-autofile-some-tags-regexp-jump-other-window',
+;; `bmkp-automatic-bookmark-mode', `bmkp-autonamed-jump',
+;; `bmkp-autonamed-jump-other-window',
+;; `bmkp-autonamed-this-buffer-jump',
+;; `bmkp-autonamed-this-buffer-jump-other-window',
+;; `bmkp-bookmark-a-file' `bmkp-bookmark-file-jump',
+;; `bmkp-bookmark-file-load-jump',
+;; `bmkp-bookmark-file-switch-jump', `bmkp-bookmark-linked-at'
+;; (Emacs 22+), `bmkp-bookmark-linked-at-mouse' (Emacs 22+),
+;; `bmkp-bookmark-list-jump',
+;; `bmkp-bookmark-set-confirm-overwrite',
+;; `bmkp-choose-navlist-from-bookmark-list',
+;; `bmkp-choose-navlist-of-type', `bmkp-clone-bookmark',
+;; `bmkp-compilation-target-set',
+;; `bmkp-compilation-target-set-all', `bmkp-copy-bookmark',
+;; `bmkp-convert-eww-bookmarks' (Emacs 25+), `bmkp-copy-tags',
+;; `bmkp-crosshairs-highlight', `bmkp-cycle',
+;; `bmkp-cycle-autonamed', `bmkp-cycle-autonamed-other-window',
+;; `bmkp-cycle-bookmark-list',
+;; `bmkp-cycle-bookmark-list-other-window', `bmkp-cycle-desktop',
+;; `bmkp-cycle-dired', `bmkp-cycle-dired-other-window',
+;; `bmkp-cycle-eww', `bmkp-cycle-eww-other-window',
+;; `bmkp-cycle-file', `bmkp-cycle-file-other-window',
+;; `bmkp-cycle-gnus', `bmkp-cycle-gnus-other-window',
+;; `bmkp-cycle-info', `bmkp-cycle-info-other-window',
+;; `bmkp-cycle-lighted', `bmkp-cycle-lighted-other-window',
+;; `bmkp-cycle-local-file', `bmkp-cycle-local-file-other-window',
+;; `bmkp-cycle-man', `bmkp-cycle-man-other-window',
+;; `bmkp-cycle-non-file', `bmkp-cycle-non-file-other-window',
+;; `bmkp-cycle-other-window', `bmkp-cycle-remote-file',
+;; `bmkp-cycle-remote-file-other-window',
+;; `bmkp-cycle-specific-buffers',
+;; `bmkp-cycle-specific-buffers-other-window',
+;; `bmkp-cycle-specific-files',
+;; `bmkp-cycle-specific-files-other-window',
+;; `bmkp-cycle-this-buffer', `bmkp-cycle-this-buffer-other-window',
+;; `bmkp-cycle-this-file', `bmkp-cycle-this-file/buffer',
+;; `bmkp-cycle-this-file/buffer-other-window',
+;; `bmkp-cycle-this-file-other-window', `bmkp-cycle-variable-list',
+;; `bmkp-cycle-url', `bmkp-cycle-url-other-window',
+;; `bmkp-delete-all-autonamed-for-this-buffer',
+;; `bmkp-delete-all-temporary-bookmarks', `bmkp-delete-bookmarks',
+;; `bmkp-describe-bookmark', `bmkp-describe-bookmark-internals',
+;; `bmkp-desktop-change-dir', `bmkp-desktop-delete',
+;; `bmkp-desktop-jump', `bmkp-desktop-read', `bmkp-dired-jump',
+;; `bmkp-dired-jump-other-window', `bmkp-dired-this-dir-jump',
+;; `bmkp-dired-this-dir-jump-other-window',
+;; `bmkp-edit-bookmark-name-and-location',
+;; `bmkp-edit-bookmark-record',
+;; `bmkp-edit-bookmark-record-file/buffer',
+;; `bmkp-edit-bookmark-record-send',
+;; `bmkp-edit-bookmark-records-send', `bmkp-edit-tags',
+;; `bmkp-edit-tags-send', `bmkp-edit-this-annotation',
+;; `bmkp-empty-file', `bmkp-eww-jump' (Emacs 25+),
+;; `bmkp-eww-jump-other-window' (Emacs 25+),
+;; `bmkp-eww-auto-bookmark-mode' (Emacs 25+),
+;; `bmkp-ffap-max-region-size', `bmkp-file-target-set',
+;; `bmkp-file-all-tags-jump',
+;; `bmkp-file-all-tags-jump-other-window',
+;; `bmkp-file-all-tags-regexp-jump',
+;; `bmkp-file-all-tags-regexp-jump-other-window', `bmkp-file-jump',
+;; `bmkp-file-jump-other-window', `bmkp-file-some-tags-jump',
+;; `bmkp-file-some-tags-jump-other-window',
+;; `bmkp-file-some-tags-regexp-jump',
+;; `bmkp-file-some-tags-regexp-jump-other-window',
+;; `bmkp-file-this-dir-all-tags-jump',
+;; `bmkp-file-this-dir-all-tags-jump-other-window',
+;; `bmkp-file-this-dir-all-tags-regexp-jump',
+;; `bmkp-file-this-dir-all-tags-regexp-jump-other-window',
+;; `bmkp-file-this-dir-jump',
+;; `bmkp-file-this-dir-jump-other-window',
+;; `bmkp-file-this-dir-some-tags-jump',
+;; `bmkp-file-this-dir-some-tags-jump-other-window',
+;; `bmkp-file-this-dir-some-tags-regexp-jump',
+;; `bmkp-file-this-dir-some-tags-regexp-jump-other-window',
+;; `bmkp-find-file', `bmkp-find-file-other-window',
+;; `bmkp-find-file-all-tags',
+;; `bmkp-find-file-all-tags-other-window',
+;; `bmkp-find-file-all-tags-regexp',
+;; `bmkp-find-file-all-tags-regexp-other-window',
+;; `bmkp-find-file-some-tags',
+;; `bmkp-find-file-some-tags-other-window',
+;; `bmkp-find-file-some-tags-regexp',
+;; `bmkp-find-file-some-tags-regexp-other-window',
+;; `bmkp-get-external-annotation',
+;; `bmkp-global-automatic-bookmark-mode' (Emacs 21+),
+;; `bmkp-gnus-jump', `bmkp-gnus-jump-other-window',
+;; `bmkp-image-jump', `bmkp-image-jump-other-window',
+;; `bmkp-info-auto-bookmark-mode' (Emacs 22+), `bmkp-info-jump',
+;; `bmkp-info-jump-other-window', `bmkp-insert-bookmark-link'
+;; (Emacs 22+), `bmkp-jump-in-navlist',
+;; `bmkp-jump-in-navlist-other-window',
+;; `bmkp-jump-to-bookmark-linked-at' (Emacs 22+),
+;; `bmkp-jump-to-bookmark-linked-at-mouse' (Emacs 22+),
+;; `bmkp-jump-to-list', `bmkp-jump-to-type',
+;; `bmkp-jump-to-type-other-window', `bmkp-list-all-tags',
+;; `bmkp-list-defuns-in-commands-file', `bmkp-local-file-jump',
+;; `bmkp-local-file-jump-other-window',
+;; `bmkp-local-non-dir-file-jump',
+;; `bmkp-local-non-dir-file-jump-other-window',
+;; `bmkp-make-bookmark-savable', `bmkp-make-bookmark-temporary',
+;; `bmkp-make-function-bookmark', `bmkp-man-jump',
+;; `bmkp-man-jump-other-window', `bmkp-menu-jump-other-window'
+;; (Emacs 20, 21), `bmkp-navlist-bmenu-list',
+;; `bmkp-next-autonamed-bookmark',
+;; `bmkp-next-autonamed-bookmark-other-window',
+;; `bmkp-next-autonamed-bookmark-other-window-repeat',
+;; `bmkp-next-autonamed-bookmark-repeat', `bmkp-next-bookmark',
+;; `bmkp-next-bookmark-list-bookmark',
+;; `bmkp-next-bookmark-list-bookmark-other-window',
+;; `bmkp-next-bookmark-list-bookmark-other-window-repeat',
+;; `bmkp-next-bookmark-list-bookmark-repeat',
+;; `bmkp-next-bookmark-other-window',
+;; `bmkp-next-bookmark-other-window-repeat',
+;; `bmkp-next-bookmark-repeat', `bmkp-next-bookmark-this-buffer',
+;; `bmkp-next-bookmark-this-buffer-other-window',
+;; `bmkp-next-bookmark-this-buffer-other-window-repeat',
+;; `bmkp-next-bookmark-this-buffer-repeat',
+;; `bmkp-next-bookmark-this-file',
+;; `bmkp-next-bookmark-this-file/buffer',
+;; `bmkp-next-bookmark-this-file/buffer-other-window',
+;; `bmkp-next-bookmark-this-file/buffer-other-window-repeat',
+;; `bmkp-next-bookmark-this-file/buffer-repeat',
+;; `bmkp-next-bookmark-this-file-other-window',
+;; `bmkp-next-bookmark-this-file-other-window-repeat',
+;; `bmkp-next-bookmark-this-file-repeat',
+;; `bmkp-next-desktop-bookmark',
+;; `bmkp-next-desktop-bookmark-other-window',
+;; `bmkp-next-desktop-bookmark-other-window-repeat',
+;; `bmkp-next-desktop-bookmark-repeat', `bmkp-next-dired-bookmark',
+;; `bmkp-next-dired-bookmark-other-window',
+;; `bmkp-next-dired-bookmark-other-window-repeat',
+;; `bmkp-next-dired-bookmark-repeat', `bmkp-next-eww-bookmark',
+;; `bmkp-next-eww-bookmark-other-window',
+;; `bmkp-next-eww-bookmark-other-window-repeat',
+;; `bmkp-next-eww-bookmark-repeat', `bmkp-next-file-bookmark',
+;; `bmkp-next-file-bookmark-other-window',
+;; `bmkp-next-file-bookmark-other-window-repeat',
+;; `bmkp-next-file-bookmark-repeat', `bmkp-next-gnus-bookmark',
+;; `bmkp-next-gnus-bookmark-other-window',
+;; `bmkp-next-gnus-bookmark-other-window-repeat',
+;; `bmkp-next-gnus-bookmark-repeat', `bmkp-next-info-bookmark',
+;; `bmkp-next-info-bookmark-other-window',
+;; `bmkp-next-info-bookmark-other-window-repeat',
+;; `bmkp-next-info-bookmark-repeat', `bmkp-next-lighted-bookmark',
+;; `bmkp-next-lighted-bookmark-other-window',
+;; `bmkp-next-lighted-bookmark-other-window-repeat',
+;; `bmkp-next-lighted-bookmark-repeat',
+;; `bmkp-next-local-file-bookmark',
+;; `bmkp-next-local-file-bookmark-other-window',
+;; `bmkp-next-local-file-bookmark-other-window-repeat',
+;; `bmkp-next-local-file-bookmark-repeat',
+;; `bmkp-next-man-bookmark', `bmkp-next-man-bookmark-other-window',
+;; `bmkp-next-man-bookmark-other-window-repeat',
+;; `bmkp-next-man-bookmark-repeat', `bmkp-next-non-file-bookmark',
+;; `bmkp-next-non-file-bookmark-other-window',
+;; `bmkp-next-non-file-bookmark-other-window-repeat',
+;; `bmkp-next-non-file-bookmark-repeat',
+;; `bmkp-next-remote-file-bookmark',
+;; `bmkp-next-remote-file-bookmark-other-window',
+;; `bmkp-next-remote-file-bookmark-other-window-repeat',
+;; `bmkp-next-remote-file-bookmark-repeat',
+;; `bmkp-next-specific-buffers-bookmark',
+;; `bmkp-next-specific-buffers-bookmark-other-window',
+;; `bmkp-next-specific-buffers-bookmark-other-window-repeat',
+;; `bmkp-next-specific-buffers-bookmark-repeat',
+;; `bmkp-next-specific-files-bookmark',
+;; `bmkp-next-specific-files-bookmark-other-window',
+;; `bmkp-next-specific-files-bookmark-other-window-repeat',
+;; `bmkp-next-specific-files-bookmark-repeat',
+;; `bmkp-next-variable-list-bookmark',
+;; `bmkp-next-variable-list-bookmark-other-window',
+;; `bmkp-next-variable-list-bookmark-other-window-repeat',
+;; `bmkp-next-variable-list-bookmark-repeat',
+;; `bmkp-next-url-bookmark', `bmkp-next-url-bookmark-other-window',
+;; `bmkp-next-url-bookmark-other-window-repeat',
+;; `bmkp-next-url-bookmark-repeat', `bmkp-next-bookmark-w32',
+;; `bmkp-next-bookmark-w32-other-window',
+;; `bmkp-next-bookmark-w32-other-window-repeat',
+;; `bmkp-next-bookmark-w32-repeat', `bmkp-non-dir-file-jump',
+;; `bmkp-non-dir-file-jump-other-window', `bmkp-non-file-jump',
+;; `bmkp-non-file-jump-other-window',
+;; `bmkp-occur-create-autonamed-bookmarks',
+;; `bmkp-ORIG-bookmark-insert', `bmkp-occur-target-set',
+;; `bmkp-occur-target-set-all', `bmkp-paste-add-tags',
+;; `bmkp-paste-replace-tags', `bmkp-previous-autonamed-bookmark',
+;; `bmkp-previous-autonamed-bookmark-other-window',
+;; `bmkp-previous-autonamed-bookmark-other-window-repeat',
+;; `bmkp-previous-autonamed-bookmark-repeat',
+;; `bmkp-previous-bookmark',
+;; `bmkp-previous-bookmark-list-bookmark',
+;; `bmkp-previous-bookmark-list-bookmark-other-window',
+;; `bmkp-previous-bookmark-list-bookmark-other-window-repeat',
+;; `bmkp-previous-bookmark-list-bookmark-repeat',
+;; `bmkp-previous-bookmark-list-repeat',
+;; `bmkp-previous-bookmark-other-window',
+;; `bmkp-previous-bookmark-other-window-repeat',
+;; `bmkp-previous-bookmark-repeat',
+;; `bmkp-previous-bookmark-this-buffer',
+;; `bmkp-previous-bookmark-this-buffer-other-window',
+;; `bmkp-previous-bookmark-this-buffer-other-window-repeat',
+;; `bmkp-previous-bookmark-this-buffer-repeat',
+;; `bmkp-previous-bookmark-this-file',
+;; `bmkp-previous-bookmark-this-file/buffer',
+;; `bmkp-previous-bookmark-this-file/buffer-other-window',
+;; `bmkp-previous-bookmark-this-file/buffer-other-window-repeat',
+;; `bmkp-previous-bookmark-this-file/buffer-repeat',
+;; `bmkp-previous-bookmark-this-file-other-window',
+;; `bmkp-previous-bookmark-this-file-other-window-repeat',
+;; `bmkp-previous-bookmark-this-file-repeat',
+;; `bmkp-previous-desktop-bookmark',
+;; `bmkp-previous-desktop-bookmark-other-window',
+;; `bmkp-previous-desktop-bookmark-other-window-repeat',
+;; `bmkp-previous-desktop-bookmark-repeat',
+;; `bmkp-previous-dired-bookmark',
+;; `bmkp-previous-dired-bookmark-other-window',
+;; `bmkp-previous-dired-bookmark-other-window-repeat',
+;; `bmkp-previous-dired-bookmark-repeat',
+;; `bmkp-previous-eww-bookmark',
+;; `bmkp-previous-eww-bookmark-other-window',
+;; `bmkp-previous-eww-bookmark-other-window-repeat',
+;; `bmkp-previous-eww-bookmark-repeat',
+;; `bmkp-previous-file-bookmark',
+;; `bmkp-previous-file-bookmark-other-window',
+;; `bmkp-previous-file-bookmark-other-window-repeat',
+;; `bmkp-previous-file-bookmark-repeat',
+;; `bmkp-previous-gnus-bookmark',
+;; `bmkp-previous-gnus-bookmark-other-window',
+;; `bmkp-previous-gnus-bookmark-other-window-repeat',
+;; `bmkp-previous-gnus-bookmark-repeat',
+;; `bmkp-previous-info-bookmark',
+;; `bmkp-previous-info-bookmark-other-window',
+;; `bmkp-previous-info-bookmark-other-window-repeat',
+;; `bmkp-previous-info-bookmark-repeat',
+;; `bmkp-previous-lighted-bookmark',
+;; `bmkp-previous-lighted-bookmark-other-window',
+;; `bmkp-previous-lighted-bookmark-other-window-repeat',
+;; `bmkp-previous-lighted-bookmark-repeat',
+;; `bmkp-previous-local-file-bookmark',
+;; `bmkp-previous-local-file-bookmark-other-window',
+;; `bmkp-previous-local-file-bookmark-other-window-repeat',
+;; `bmkp-previous-local-file-bookmark-repeat',
+;; `bmkp-previous-man-bookmark',
+;; `bmkp-previous-man-bookmark-other-window',
+;; `bmkp-previous-man-bookmark-other-window-repeat',
+;; `bmkp-previous-man-bookmark-repeat',
+;; `bmkp-previous-non-file-bookmark',
+;; `bmkp-previous-non-file-bookmark-other-window',
+;; `bmkp-previous-non-file-bookmark-other-window-repeat',
+;; `bmkp-previous-non-file-bookmark-repeat',
+;; `bmkp-previous-remote-file-bookmark',
+;; `bmkp-previous-remote-file-bookmark-other-window',
+;; `bmkp-previous-remote-file-bookmark-other-window-repeat',
+;; `bmkp-previous-remote-file-bookmark-repeat',
+;; `bmkp-previous-specific-buffers-bookmark',
+;; `bmkp-previous-specific-buffers-bookmark-other-window',
+;; `bmkp-previous-specific-buffers-bookmark-other-window-repeat',
+;; `bmkp-previous-specific-buffers-bookmark-repeat',
+;; `bmkp-previous-specific-files-bookmark',
+;; `bmkp-previous-specific-files-bookmark-other-window',
+;; `bmkp-previous-specific-files-bookmark-other-window-repeat',
+;; `bmkp-previous-specific-files-bookmark-repeat',
+;; `bmkp-previous-variable-list-bookmark',
+;; `bmkp-previous-variable-list-bookmark-other-window',
+;; `bmkp-previous-variable-list-bookmark-other-window-repeat',
+;; `bmkp-previous-variable-list-bookmark-repeat',
+;; `bmkp-previous-url-bookmark',
+;; `bmkp-previous-url-bookmark-other-window',
+;; `bmkp-previous-url-bookmark-other-window-repeat',
+;; `bmkp-previous-url-bookmark-repeat',
+;; `bmkp-previous-bookmark-w32',
+;; `bmkp-previous-bookmark-w32-other-window',
+;; `bmkp-previous-bookmark-w32-other-window-repeat',
+;; `bmkp-previous-bookmark-w32-repeat',
+;; `bmkp-purge-notags-autofiles', `bmkp-read-bookmark-for-type',
+;; `bmkp-region-jump',
+;; `bmkp-region-jump-narrow-indirect-other-window',
+;; `bmkp-region-jump-other-window', `bmkp-remote-file-jump',
+;; `bmkp-remote-file-jump-other-window',
+;; `bmkp-remote-non-dir-file-jump',
+;; `bmkp-temote-non-dir-file-jump-other-window',
+;; `bmkp-remove-all-tags', `bmkp-remove-tags',
+;; `bmkp-remove-tags-from-all', `bmkp-rename-tag',
+;; `bmkp-retrieve-icicle-search-hits',
+;; `bmkp-retrieve-more-icicle-search-hits',
+;; `bmkp-revert-bookmark-file',
+;; `bmkp-save-bookmarks-this-file/buffer',
+;; `bmkp-save-menu-list-state', `bmkp-send-bug-report',
+;; `bmkp-set-autonamed-bookmark',
+;; `bmkp-set-autonamed-bookmark-at-line',
+;; `bmkp-set-autonamed-regexp-buffer',
+;; `bmkp-set-autonamed-regexp-region',
+;; `bmkp-set-bookmark-file-bookmark', `bmkp-set-desktop-bookmark',
+;; `bmkp-set-dired-bookmark-for-files',
+;; `bmkp-set-eww-bookmark-here' (Emacs 25+),
+;; `bmkp-set-grep-command-bookmark' (Emacs 26+),
+;; `bmkp-set-icicle-search-hits-bookmark',
+;; `bmkp-set-info-bookmark-with-node-name' (Emacs 22+),
+;; `bmkp-set-izones-bookmark', `bmkp-set-kmacro-bookmark' (Emacs
+;; 22+), `bmkp-set-kmacro-list-bookmark' (Emacs 22+),
+;; `bmkp-set-sequence-bookmark', `bmkp-set-snippet-bookmark',
+;; `bmkp-set-tag-value', `bmkp-set-tag-value-for-navlist',
+;; `bmkp-set-variable-list-bookmark',
+;; `bmkp-show-this-annotation-read-only',
+;; `bmkp-snippet-to-kill-ring', `bmkp-some-tags-jump',
+;; `bmkp-some-tags-jump-other-window',
+;; `bmkp-some-tags-regexp-jump',
+;; `bmkp-some-tags-regexp-jump-other-window',
+;; `bmkp-specific-buffers-jump',
+;; `bmkp-specific-buffers-jump-other-window',
+;; `bmkp-specific-files-jump',
+;; `bmkp-specific-files-jump-other-window', `bmkp-store-org-link'
+;; (Emacs 24.4+), `bmkp-switch-bookmark-file',
+;; `bmkp-switch-bookmark-file-create',
+;; `bmkp-switch-to-bookmark-file-this-file/buffer',
+;; `bmkp-switch-to-last-bookmark-file', `bmkp-tag-a-file',
+;; `bmkp-temporary-bookmarking-mode', `bmkp-temporary-jump',
+;; `bmkp-temporary-jump-other-window',
+;; `bmkp-this-buffer-bmenu-list', `bmkp-this-buffer-jump',
+;; `bmkp-this-buffer-jump-other-window',
+;; `bmkp-this-file-bmenu-list', `bmkp-this-file/buffer-bmenu-list',
+;; `bmkp-toggle-autonamed-bookmark-set/delete',
+;; `bmkp-toggle-autotemp-on-set',
+;; `bmkp-toggle-bookmark-set-refreshes',
+;; `bmkp-toggle-eww-auto-type' (Emacs 25+),
+;; `bmkp-toggle-info-auto-type' (Emacs 22+),
+;; `bmkp-toggle-saving-bookmark-file',
+;; `bmkp-toggle-saving-menu-list-state',
+;; `bmkp-toggle-temporary-bookmark',
+;; `bmkp-turn-on-automatic-bookmark-mode' (Emacs 21+),
+;; `bmkp-types-alist', `bmkp-unomit-all', `bmkp-untag-a-file',
+;; `bmkp-url-target-set', `bmkp-url-jump',
+;; `bmkp-url-jump-other-window', `bmkp-variable-list-jump',
+;; `bmkp-version', `bmkp-visit-external-annotation',
+;; `bmkp-w32-browser-jump', `bmkp-w3m-jump',
+;; `bmkp-w3m-jump-other-window',
+;; `bmkp-wrap-bookmark-with-last-kbd-macro'.
+;;
+;; User options defined here:
+;;
+;; `bmkp-annotation-modes-inherit-from', `bmkp-autofile-filecache',
+;; `bmkp-automatic-bookmark-min-distance',
+;; `bmkp-automatic-bookmark-mode-delay',
+;; `bmkp-automatic-bookmark-mode-lighter',
+;; `bmkp-automatic-bookmark-set-function',
+;; `bmkp-autoname-bookmark-function', `bmkp-autoname-format',
+;; `bmkp-autotemp-bookmark-predicates',
+;; `bmkp-bookmark-name-length-max',
+;; `bmkp-count-multi-mods-as-one-flag', `bmkp-crosshairs-flag',
+;; `bmkp-default-bookmark-name',
+;; `bmkp-default-handlers-for-file-types',
+;; `bmkp-desktop-default-directory',
+;; `bmkp-desktop-jump-save-before-flag',
+;; `bmkp-desktop-no-save-vars', `bmkp-eww-auto-type' (Emacs 25+),
+;; `bmkp-eww-buffer-renaming' (Emacs 25+),
+;; `bmkp-eww-generate-buffer-flag' (Emacs 25+),
+;; `bmkp-eww-replace-keys-flag' (Emacs 25+),
+;; `bmkp-guess-default-handler-for-file-flag',
+;; `bmkp-handle-region-function', `bmkp-incremental-filter-delay',
+;; `bmkp-info-auto-type' (Emacs 22+),
+;; `bmkp-info-sort-ignores-directories-flag',
+;; `bmkp-last-as-first-bookmark-file',
+;; `bmkp-menu-popup-max-length', `bmkp-new-bookmark-default-names',
+;; `bmkp-other-window-pop-to-flag', `bmkp-prompt-for-tags-flag',
+;; `bmkp-properties-to-keep', `bmkp-read-bookmark-file-hook',
+;; `bmkp-region-search-size', `bmkp-save-new-location-flag',
+;; `bmkp-sequence-jump-display-function',
+;; `bmkp-show-end-of-region-flag', `bmkp-sort-comparer',
+;; `bmkp-su-or-sudo-regexp', `bmkp-tags-for-completion',
+;; `bmkp-temporary-bookmarking-mode',
+;; `bmkp-temporary-bookmarking-mode-hook',
+;; `bmkp-temporary-bookmarking-mode-lighter',
+;; `bmkp-this-file/buffer-cycle-sort-comparer', `bmkp-use-region',
+;; `bmkp-w3m-allow-multiple-buffers-flag',
+;; `bmkp-write-bookmark-file-hook'.
+;;
+;; Non-interactive functions defined here:
+;;
+;; `bmkext-jump-gnus', `bmkext-jump-man', `bmkext-jump-w3m',
+;; `bmkext-jump-woman', `bmkp-add-jump-to-list-button',
+;; `bmkp-all-exif-data', `bmkp-all-tags-alist-only',
+;; `bmkp-all-tags-regexp-alist-only', `bmkp-alpha-cp',
+;; `bmkp-alpha-p', `bmkp-annotated-alist-only',
+;; `bmkp-annotated-bookmark-p', `bmkp-annotated-cp',
+;; `bmkp-annotation-or-bookmark-description',
+;; `bmkp-autofile-alist-only', `bmkp-autofile-all-tags-alist-only',
+;; `bmkp-autofile-all-tags-regexp-alist-only',
+;; `bmkp-autofile-bookmark-p',
+;; `bmkp-autofile-some-tags-alist-only',
+;; `bmkp-autofile-some-tags-regexp-alist-only',
+;; `bmkp-autoname-bookmark-function-default',
+;; `bmkp-autonamed-alist-only',
+;; `bmkp-autonamed-bookmark-for-buffer-p',
+;; `bmkp-autonamed-bookmark-p',
+;; `bmkp-autonamed-this-buffer-alist-only',
+;; `bmkp-autonamed-this-buffer-bookmark-p',
+;; `bmkp-bookmark-creation-cp', `bmkp-bookmark-data-from-record',
+;; `bmkp-bookmark-description', `bmkp-bookmark-last-access-cp',
+;; `bmkp-bookmark-file-alist-only',
+;; `bmkp-bookmark-file-bookmark-p',
+;; `bmkp-bookmark-list-alist-only',
+;; `bmkp-bookmark-list-bookmark-p', `bmkp-bookmark-name-member',
+;; `bmkp-bookmark-record-from-name', `bmkp-buffer-alist-only',
+;; `bmkp-buffer-last-access-cp', `bmkp-buffer-names',
+;; `bmkp-compilation-file+line-at', `bmkp-completing-read-1',
+;; `bmkp-completing-read-bookmarks',
+;; `bmkp-completing-read-buffer-name',
+;; `bmkp-completing-read-file-name', `bmkp-completing-read-lax',
+;; `bmkp-cp-not', `bmkp-create-variable-list-bookmark',
+;; `bmkp-current-bookmark-list-state', `bmkp-current-sort-order',
+;; `bmkp-cycle-1', `bmkp-default-bookmark-file',
+;; `bmkp-default-bookmark-name', `bmkp-default-handler-for-file',
+;; `bmkp-default-handler-user', `bmkp-delete-autonamed-no-confirm',
+;; `bmkp-delete-autonamed-this-buffer-no-confirm',
+;; `bmkp-delete-bookmark-name-from-list',
+;; `bmkp-delete-temporary-no-confirm', `bmkp-desktop-alist-only',
+;; `bmkp-desktop-bookmark-p',
+;; `bmkp-desktop-file-p',`bmkp-desktop-kill', `bmkp-desktop-save',
+;; `bmkp-desktop-save-as-last', `bmkp-dired-alist-only',
+;; `bmkp-dired-bookmark-p', `bmkp-dired-remember-*-marks',
+;; `bmkp-dired-subdirs', `bmkp-dired-this-dir-alist-only',
+;; `bmkp-dired-wildcards-alist-only',
+;; `bmkp-dired-this-dir-bookmark-p',
+;; `bmkp-dired-wildcards-bookmark-p',
+;; `bmkp-edit-bookmark-record-mode',
+;; `bmkp-edit-bookmark-records-mode', `bmkp-edit-tags-mode',
+;; `bmkp-end-position-post-context',
+;; `bmkp-end-position-pre-context', `bmkp-every',
+;; `bmkp-eww-alist-only' (Emacs 25+), `bmkp-eww-bookmark-p' (Emacs
+;; 25+), `bmkp-eww-cp' (Emacs 25+), `bmkp-eww-new-buffer-name'
+;; (Emacs 25+), `bmkp-eww-rename-buffer' (Emacs 25+),
+;; `bmkp-eww-title' (Emacs 25+), `bmkp-eww-url' (Emacs 25+),
+;; `bmkp-ffap-guesser', `bmkp-file-alist-only',
+;; `bmkp-file-all-tags-alist-only',
+;; `bmkp-file-all-tags-regexp-alist-only', `bmkp-file-alpha-cp',
+;; `bmkp-file-attribute-0-cp', `bmkp-file-attribute-1-cp',
+;; `bmkp-file-attribute-2-cp', `bmkp-file-attribute-3-cp',
+;; `bmkp-file-attribute-4-cp', `bmkp-file-attribute-5-cp',
+;; `bmkp-file-attribute-6-cp', `bmkp-file-attribute-7-cp',
+;; `bmkp-file-attribute-8-cp', `bmkp-file-attribute-9-cp',
+;; `bmkp-file-attribute-10-cp', `bmkp-file-attribute-11-cp',
+;; `bmkp-file-bookmark-p', `bmkp-file-names', `bmkp-file-remote-p',
+;; `bmkp-file-some-tags-alist-only',
+;; `bmkp-file-some-tags-regexp-alist-only',
+;; `bmkp-file-this-dir-alist-only',
+;; `bmkp-file-this-dir-all-tags-alist-only',
+;; `bmkp-file-this-dir-all-tags-regexp-alist-only',
+;; `bmkp-file-this-dir-bookmark-p',
+;; `bmkp-file-this-dir-some-tags-alist-only',
+;; `bmkp-file-this-dir-some-tags-regexp-alist-only',
+;; `bmkp-find-tag-default-as-regexp' (Emacs 22-24.2),
+;; `bmkp-flagged-bookmark-p', `bmkp-flagged-cp', `bmkp-float-time',
+;; `bmkp-format-spec', `bmkp-full-tag', `bmkp-function-alist-only',
+;; `bmkp-function-bookmark-p', `bmkp-get-autofile-bookmark',
+;; `bmkp-get-bookmark', `bmkp-get-bookmark-in-alist',
+;; `bmkp-get-buffer-name', `bmkp-get-end-position',
+;; `bmkp-get-tag-value', `bmkp-get-tags', `bmkp-get-visit-time',
+;; `bmkp-get-visits-count', `bmkp-gnus-alist-only',
+;; `bmkp-gnus-bookmark-p', `bmkp-gnus-cp', `bmkp-goto-position',
+;; `bmkp-handle-region-default',
+;; `bmkp-handle-region+narrow-indirect', `bmkp-handler-cp',
+;; `bmkp-handler-pred', `bmkp-has-tag-p',
+;; `bmkp-icicles-search-hits-alist-only',
+;; `bmkp-icicles-search-hits-bookmark-p', `bmkp-image-alist-only',
+;; `bmkp-image-bookmark-p', `bmkp-info-alist-only',
+;; `bmkp-info-bookmark-p', `bmkp-info-node-name-cp',
+;; `bmkp-info-position-cp', `bmkp-isearch-bookmarks' (Emacs 23+),
+;; `bmkp-isearch-bookmarks-regexp' (Emacs 23+),
+;; `bmkp-isearch-next-bookmark-buffer' (Emacs 23+), `bmkp-jump-1',
+;; `bmkp-jump-bookmark-file', `bmkp-jump-bookmark-list',
+;; `bmkp-jump-desktop', `bmkp-jump-dired', `bmkp-jump-eww' (Emacs
+;; 25+), `bmkp-jump-function', `bmkp-jump-gnus',
+;; `bmkp-jump-icicle-search-hits', `bmkp-jump-kmacro-list' (Emacs
+;; 22+), `bmkp-jump-man', `bmkp-jump-sequence',
+;; `bmkp-jump-snippet', `bmkp-jump-url-browse',
+;; `bmkp-jump-variable-list', `bmkp-jump-w3m',
+;; `bmkp-jump-w3m-new-buffer', `bmkp-jump-w3m-new-buffer',
+;; `bmkp-jump-w3m-only-one-buffer',
+;; `bmkp-jump-w3m-only-one-buffer', `bmkp-jump-woman',
+;; `bmkp-kmacro-list-bookmark-p',
+;; `bmkp-last-specific-buffer-alist-only',
+;; `bmkp-last-specific-buffer-p',
+;; `bmkp-last-specific-file-alist-only',
+;; `bmkp-last-specific-file-p', `bmkp-list-position',
+;; `bmkp-local-directory-bookmark-p',
+;; `bmkp-local-file-accessed-more-recently-cp',
+;; `bmkp-local-file-alist-only', `bmkp-local-file-bookmark-p',
+;; `bmkp-local-file-size-cp', `bmkp-local-file-type-cp',
+;; `bmkp-local-non-dir-file-alist-only',
+;; `bmkp-local-non-dir-file-bookmark-p',
+;; `bmkp-local-file-updated-more-recently-cp',
+;; `bmkp-make-bookmark-file-record',
+;; `bmkp-make-bookmark-list-record', `bmkp-make-desktop-record',
+;; `bmkp-make-dired-record', `bmkp-make-eww-record' (Emacs 25+),
+;; `bmkp-make-gnus-record', `bmkp-make-icicle-search-hits-record',
+;; `bmkp-make-kmacro-list-record' (Emacs 22+),
+;; `bmkp-make-man-record', `bmkp-make-obsolete',
+;; `bmkp-make-obsolete-variable', `bmkp-make-plain-predicate',
+;; `bmkp-make-record-for-target-file', `bmkp-make-sequence-record',
+;; `bmkp-make-url-browse-record', `bmkp-make-variable-list-record',
+;; `bmkp-make-w3m-record', `bmkp-make-woman-record' (Emacs 21+),
+;; `bmkp-man-alist-only', `bmkp-man-bookmark-p',
+;; `bmkp-marked-bookmark-p', `bmkp-marked-bookmarks-only',
+;; `bmkp-marked-cp', `bmkp-maybe-save-bookmarks',
+;; `bmkp-modified-bookmark-p', `bmkp-modified-cp',
+;; `bmkp-msg-about-sort-order', `bmkp-multi-sort',
+;; `bmkp-names-same-bookmark-p', `bmkp-navlist-bookmark-p',
+;; `bmkp-new-bookmark-default-names',
+;; `bmkp-non-autonamed-alist-only', `bmkp-non-dir-file-alist-only',
+;; `bmkp-non-dir-file-bookmark-p', `bmkp-non-file-alist-only',
+;; `bmkp-non-file-bookmark-p', `bmkp-non-invokable-alist-only',
+;; `bmkp-non-invokable-bookmark-p',
+;; `bmkp-not-near-other-automatic-bmks', `bmkp-omitted-alist-only',
+;; `bmkp-orphaned-file-alist-only',
+;; `bmkp-orphaned-file-bookmark-p',
+;; `bmkp-orphaned-local-file-alist-only',
+;; `bmkp-orphaned-local-file-bookmark-p',
+;; `bmkp-orphaned-remote-file-alist-only',
+;; `bmkp-orphaned-remote-file-bookmark-p',
+;; `bmkp-pop-to-readable-marker', `bmkp-position-after-whitespace',
+;; `bmkp-position-before-whitespace', `bmkp-position-cp',
+;; `bmkp-position-post-context',
+;; `bmkp-position-post-context-region',
+;; `bmkp-position-pre-context', `bmkp-position-pre-context-region',
+;; `bmkp-printable-vars+vals', `bmkp-propertize',
+;; `bmkp-readable-p', `bmkp-read-bookmark-file-default',
+;; `bmkp-read-bookmark-file-name', `bmkp-read-buffers',
+;; `bmkp-read-files', `bmkp-read-from-whole-string',
+;; `bmkp-read-regexp', `bmkp-read-tag-completing',
+;; `bmkp-read-tags', `bmkp-read-tags-completing',
+;; `bmkp-read-variable', `bmkp-read-variables-completing',
+;; `bmkp-record-visit', `bmkp-refresh-latest-bookmark-list',
+;; `bmkp-refresh-menu-list', `bmkp-refresh/rebuild-menu-list',
+;; `bmkp-regexp-filtered-annotation-alist-only',
+;; `bmkp-regexp-filtered-bookmark-name-alist-only',
+;; `bmkp-regexp-filtered-file-name-alist-only',
+;; `bmkp-regexp-filtered-tags-alist-only',
+;; `bmkp-region-alist-only', `bmkp-region-bookmark-p',
+;; `bmkp-remote-file-alist-only', `bmkp-remote-file-bookmark-p',
+;; `bmkp-remote-non-dir-file-alist-only',
+;; `bmkp-remote-non-dir-file-bookmark-p', `bmkp-remove-dups',
+;; `bmkp-remove-if', `bmkp-remove-if-not', `bmkp-remove-omitted',
+;; `bmkp-rename-for-marked-and-omitted-lists',
+;; `bmkp-repeat-command', `bmkp-replace-existing-bookmark',
+;; `bmkp-reset-bmkp-store-org-link-checking-p' (Emacs 24.4+),
+;; `bmkp-retrieve-icicle-search-hits-1',
+;; `bmkp-root-or-sudo-logged-p', `bmkp-same-creation-time-p',
+;; `bmkp-same-file-p', `bmkp-save-new-region-location',
+;; `bmkp-select-buffer-other-window', `bmkp-sequence-alist-only',
+;; `bmkp-sequence-bookmark-p', `bmkp-set-automatic-bookmark',
+;; `bmkp-set-tag-value-for-bookmarks', `bmkp-set-union',
+;; `bmkp-snippet-alist-only', `bmkp-snippet-bookmark-p',
+;; `bmkp-some', `bmkp-some-marked-p', `bmkp-some-tags-alist-only',
+;; `bmkp-some-tags-regexp-alist-only', `bmkp-some-unmarked-p',
+;; `bmkp-sorting-description', `bmkp-sort-omit', `bmkp-sound-jump',
+;; `bmkp-specific-buffers-alist-only',
+;; `bmkp-specific-files-alist-only', `bmkp-store-org-link-1',
+;; `bmkp-string-less-case-fold-p', `bmkp-tagged-alist-only',
+;; `bmkp-tagged-bookmark-p', `bmkp-tagged-cp', `bmkp-tag-name',
+;; `bmkp-tags-in-bookmark-file', `bmkp-tags-list',
+;; `bmkp-temporary-alist-only', `bmkp-temporary-bookmark-p',
+;; `bmkp-thing-at-point', `bmkp-this-buffer-alist-only',
+;; `bmkp-this-buffer-p', `bmkp-this-file-alist-only',
+;; `bmkp-this-file/buffer-alist-only', `bmkp-this-file-p',
+;; `bmkp-unmarked-bookmarks-only', `bmkp-unpropertized-string',
+;; `bmkp-untagged-alist-only', `bmkp-upcase',
+;; `bmkp-update-autonamed-bookmark', `bmkp-url-alist-only',
+;; `bmkp-url-bookmark-p', `bmkp-url-browse-alist-only',
+;; `bmkp-url-browse-bookmark-p', `bmkp-url-cp',
+;; `bmkp-variable-list-alist-only',
+;; `bmkp-variable-list-bookmark-p', `bmkp-visited-more-cp',
+;; `bmkp-w3m-alist-only', `bmkp-w3m-bookmark-p', `bmkp-w3m-cp',
+;; `bmkp-w3m-set-new-buffer-name',
+;; `bmkp-write-alist-bookmarks-to-file'.
+;;
+;; Internal variables defined here:
+;;
+;; `bmkp-after-set-hook', `bmkp-autofile-history',
+;; `bmkp-automatic-bookmark-mode-timer',
+;; `bmkp-automatic-bookmarks', `bmkp-autonamed-history',
+;; `bmkp-autotemp-all-when-set-p', `bmkp-before-jump-hook',
+;; `bmkp-bookmark-file-history', `bmkp-bookmark-list-history',
+;; `bmkp-bookmark-set-confirms-overwrite-p',
+;; `bmkp-buffer-bookmark-p', `bmkp-current-bookmark-file',
+;; `bmkp-current-nav-bookmark', `bmkp-desktop-current-file',
+;; `bmkp-desktop-history', `bmkp-dired-history',
+;; `bmkp-edit-bookmark-record-mode-map',
+;; `bmkp-edit-bookmark-records-mode-map',
+;; `bmkp-edit-bookmark-records-number', `bmkp-edit-tags-mode-map',
+;; `bmkp-eww-history' (Emacs 25+), `bmkp-eww-jumping-p' (Emacs
+;; 25+), `bmkp-eww-new-buf-name' (Emacs 25+),
+;; `bmkp-file-bookmark-handlers', `bmkp-file-history',
+;; `bmkp-gnus-history', `bmkp-icicles-search-hits-retrieve-more',
+;; `bmkp-image-history', `bmkp-info-history',
+;; `bmkp-isearch-bookmarks' (Emacs 23+),
+;; `bmkp-jump-display-function', `bmkp-jump-other-window-map',
+;; `bmkp-last-bmenu-state-file', `bmkp-last-bookmark-file',
+;; `bmkp-last-save-flag-value', `bmkp-last-specific-buffer',
+;; `bmkp-last-specific-file', `bmkp-latest-bookmark-alist',
+;; `bmkp-local-file-history', `bmkp-man-history',
+;; `bmkp-modified-bookmarks', `bmkp-nav-alist',
+;; `bmkp-non-file-filename', `bmkp-non-file-history',
+;; `bmkp-region-history', `bmkp-remote-file-history',
+;; `bmkp-return-buffer', `bmkp-reverse-multi-sort-p',
+;; `bmkp-reverse-sort-p', `bmkp-snippet-history',
+;; `bmkp-sorted-alist', `bmkp-specific-buffers-history',
+;; `bmkp-specific-files-history', `bmkp-store-org-link-checking-p',
+;; `bmkp-tag-history', `bmkp-tags-alist', `bmkp-temporary-history',
+;; `bmkp-url-history', `bmkp-use-w32-browser-p',
+;; `bmkp-variable-list-history', `bmkp-version-number',
+;; `bmkp-w3m-history'.
+;;
+;;
+;; ***** NOTE: The following commands defined in `bookmark.el'
+;; have been REDEFINED HERE:
+;;
+;; `bookmark-default-annotation-text', `bookmark-delete',
+;; `bookmark-edit-annotation-mode', `bookmark-insert',
+;; `bookmark-insert-annotation',
+;; `bookmark-insert-current-bookmark', `bookmark-insert-location',
+;; `bookmark-jump', `bookmark-jump-other-frame',
+;; `bookmark-jump-other-window', `bookmark-load',
+;; `bookmark-relocate', `bookmark-rename', `bookmark-save',
+;; `bookmark-send-edited-annotation', `bookmark-set',
+;; `bookmark-set-name', `bookmark-yank-word'.
+;;
+;;
+;; ***** NOTE: The following user options defined in `bookmark.el'
+;; have been REDEFINED HERE:
+;;
+;; `bookmark-automatically-show-annotations', `bookmark-sort-flag'
+;; (document non-use), `bookmark-version-control'.
+;;
+;;
+;; ***** NOTE: The following non-interactive functions defined in
+;; `bookmark.el' have been REDEFINED HERE:
+;;
+;; `bookmark--jump-via', `bookmark-alist-from-buffer',
+;; `bookmark-all-names', `bookmark-completing-read',
+;; `bookmark-default-handler', `bookmark-edit-annotation' (command
+;; here), `bookmark-exit-hook-internal', `bookmark-get-bookmark',
+;; `bookmark-get-bookmark-record' (Emacs 20-22),
+;; `bookmark-get-handler' (Emacs 20-22),
+;; `bookmark-handle-bookmark', `bookmark-import-new-list',
+;; `bookmark-jump-noselect' (Emacs 20-22), `bookmark-location',
+;; `bookmark-make-record', `bookmark-make-record-default',
+;; `bookmark-maybe-load-default-file', `bookmark-maybe-rename',
+;; `bookmark-prop-get' (Emacs 20-22), `bookmark-prop-set',
+;; `bookmark-show-annotation' (command here),
+;; `bookmark-show-all-annotations' (command here), `bookmark-store'
+;; (Emacs 20-22), `bookmark-write-file'.
+;;
+;;
+;; ***** NOTE: The following internal variables defined in
+;; `bookmark.el' have been REDEFINED HERE:
+;;
+;; `bookmark-alist' (doc string only),
+;; `bookmark-make-record-function' (Emacs 20-22),
+;; `bookmarks-already-loaded' (doc string only).
+;;
+;;
+;; ***** NOTE: The following function defined in `info.el'
+;; has been REDEFINED HERE:
+;;
+;; `Info-bookmark-make-record' (Emacs 20-22).
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(unless (fboundp 'file-remote-p) (require 'ffap)) ;; ffap-file-remote-p
+(eval-when-compile (require 'gnus)) ;; mail-header-id (really in `nnheader.el')
+(eval-when-compile (require 'gnus-sum)) ;; gnus-summary-article-header
+(eval-when-compile (require 'cl)) ;; case, multiple-value-bind, typecase (plus, for Emacs 20: dolist, push)
+
+(when (and (require 'thingatpt+ nil t) ;; (no error if not found):
+ (fboundp 'tap-put-thing-at-point-props)) ; >= 2012-08-21
+ (tap-define-aliases-wo-prefix)
+ (tap-put-thing-at-point-props))
+;; region-or-non-nil-symbol-name-nearest-point, symbol-nearest-point
+
+(when (> emacs-major-version 21) (require 'font-lock+ nil t)) ;; font-lock-ignore (text property)
+
+(require 'bookmark)
+;; bookmark-alist, bookmark-alist-modification-count, bookmark-annotation-name,
+;; bookmark-automatically-show-annotations, bookmark-bmenu-bookmark,
+;; bookmark-bmenu-surreptitiously-rebuild-list, bookmark-buffer-file-name, bookmark-buffer-name,
+;; bookmark-completion-ignore-case, bookmark-current-bookmark, bookmark-default-file,
+;; bookmark-edit-annotation, bookmark-get-annotation, bookmark-get-bookmark, bookmark-get-bookmark-record,
+;; bookmark-get-filename, bookmark-get-front-context-string, bookmark-get-handler, bookmark-get-position,
+;; bookmark-get-rear-context-string, bookmark-insert-file-format-version-stamp, bookmark-kill-line,
+;; bookmark-make-record, bookmark-maybe-historicize-string, bookmark-maybe-upgrade-file-format,
+;; bookmark-menu-popup-paned-menu, bookmark-name-from-full-record, bookmark-name-from-record,
+;; bookmark-popup-menu-and-apply-function, bookmark-prop-get, bookmark-save-flag, bookmark-search-size,
+;; bookmark-set-annotation, bookmark-set-filename, bookmark-set-position, bookmark-time-to-save-p,
+;; bookmark-use-annotations, bookmark-yank-point
+
+
+;; Some general Renamings.
+;;
+;; 1. Fix incompatibility introduced by gratuitous Emacs name change.
+;;
+(cond ((and (fboundp 'bookmark-name-from-record) (not (fboundp 'bookmark-name-from-full-record)))
+ (defalias 'bookmark-name-from-full-record 'bookmark-name-from-record))
+ ((and (fboundp 'bookmark-name-from-full-record) (not (fboundp 'bookmark-name-from-record)))
+ (defalias 'bookmark-name-from-record 'bookmark-name-from-full-record)))
+
+;; 2. The vanilla name of the first is misleading, as it returns only the cdr of the record.
+;; The second is for consistency.
+;;
+(defalias 'bmkp-bookmark-data-from-record 'bookmark-get-bookmark-record)
+(defalias 'bmkp-bookmark-name-from-record 'bookmark-name-from-full-record)
+
+;; 3. Do these up front. Emacs 23 made incompatible change to require all args.
+;;
+(defun bmkp-make-obsolete (obsolete-name current-name &optional when)
+ "Same as `make-obsolete', but usable also for Emacs prior to Emacs 23."
+ (if (< emacs-major-version 23)
+ (make-obsolete obsolete-name current-name)
+ (make-obsolete obsolete-name current-name when)))
+
+(defun bmkp-make-obsolete-variable (obsolete-name current-name &optional when access-type)
+ "Same as `make-obsolete-variable', but usable also for Emacs prior to Emacs 23."
+ (if (< emacs-major-version 23)
+ (make-obsolete-variable obsolete-name current-name)
+ (make-obsolete-variable obsolete-name current-name when)))
+
+
+
+(eval-when-compile
+ (or (condition-case nil
+ (load-library "bookmark+-mac") ; Use load-library to ensure latest .elc.
+ (error nil))
+ (require 'bookmark+-mac))) ; Require, so can load separately if not on `load-path'.
+;; bmkp-define-cycle-command, bmkp-define-file-sort-predicate, bmkp-define-next+prev-cycle-commands,
+;; bmkp-with-help-window, bmkp-with-output-to-plain-temp-buffer
+
+(eval-when-compile (require 'bookmark+-bmu))
+;; bmkp-bmenu-before-hide-marked-alist, bmkp-bmenu-before-hide-unmarked-alist, bmkp-bmenu-commands-file,
+;; bmkp-replace-regexp-in-string, bmkp-bmenu-filter-function, bmkp-bmenu-filter-pattern,
+;; bmkp-bmenu-first-time-p, bmkp-flagged-bookmarks, bmkp-bmenu-goto-bookmark-named,
+;; bmkp-bmenu-marked-bookmarks, bmkp-bmenu-omitted-bookmarks, bmkp-bmenu-refresh-menu-list,
+;; bmkp-bmenu-show-all, bmkp-bmenu-state-file, bmkp-bmenu-title, bmkp-looking-at-p,
+;; bmkp-maybe-unpropertize-bookmark-names, bmkp-sort-orders-alist, bookmark-bmenu-toggle-filenames
+
+
+;; (eval-when-compile (require 'bookmark+-lit nil t))
+;; bmkp-light-bookmark, bmkp-light-bookmarks, bmkp-light-this-buffer
+
+
+;; For the redefinition of `bookmark-get-bookmark'.
+(provide 'bookmark+-1) ; Ensure this library is loaded before we compile it.
+(require 'bookmark+-1) ; So be sure to put this library in your `load-path' before
+ ; trying to byte-compile it.
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Quiet the byte-compiler
+
+(defvar bmkp-auto-light-when-set) ; In `bookmark+-lit.el'
+(defvar bmkp-auto-light-when-jump) ; In `bookmark+-lit.el'
+(defvar bmkp-bmenu-buffer) ; In `bookmark+.el'
+(defvar bmkp-edit-bookmark-record-mode-map) ; Here, via `define-derived-mode'
+(defvar bmkp-edit-bookmark-records-mode-map) ; Here, via `define-derived-mode'
+(defvar bmkp-edit-tags-mode-map) ; Here, via `define-derived-mode'
+(defvar bmkp-eww-auto-type) ; Here (Emacs 25+)
+(defvar bmkp-eww-buffer-renaming) ; Here (Emacs 25+)
+(defvar bmkp-eww-generate-buffer-flag) ; Here (Emacs 25+)
+(defvar bmkp-eww-jumping-p) ; Here (Emacs 25+)
+(defvar bmkp-eww-new-buf-name) ; Here (Emacs 25+)
+(defvar bmkp-eww-replace-keys-flag) ; Here (Emacs 25+)
+(defvar bmkp-info-auto-type) ; Here (Emacs 22+)
+(defvar bmkp-light-priorities) ; In `bookmark+-lit.el'
+(defvar bmkp-temporary-bookmarking-mode) ; Here
+(defvar bmkp-global-automatic-bookmark-mode) ; Here, via `define-globalized-minor-mode'
+(defvar bookmark-current-point) ; In `bookmark.el', but not in Emacs 23+
+(defvar bookmark-edit-annotation-text-func) ; In `bookmark.el'
+(defvar bookmark-file-coding-system) ; In `bookmark.el' (Emacs 25.2+)
+(defvar bookmark-read-annotation-text-func) ; In `bookmark.el', but not in Emacs 23+
+(defvar bookmark-make-record-function) ; In `bookmark.el'
+(defvar desktop-basefilename) ; In `desktop.el' (Emacs < 22)
+(defvar desktop-base-file-name) ; In `desktop.el'
+(defvar desktop-buffer-args-list) ; In `desktop.el'
+(defvar desktop-delay-hook) ; In `desktop.el'
+(defvar desktop-dirname) ; In `desktop.el'
+(defvar desktop-file-modtime) ; In `desktop.el'
+(defvar desktop-globals-to-save) ; In `desktop.el'
+(defvar desktop-save-mode) ; In `desktop.el'
+(defvar desktop-save) ; In `desktop.el'
+(defvar dired-actual-switches) ; In `dired.el'
+(defvar dired-buffers) ; In `dired.el'
+(defvar dired-directory) ; In `dired.el'
+(defvar dired-guess-shell-case-fold-search) ; In `dired-x.el'
+(defvar dired-subdir-alist) ; In `dired.el'
+(defvar eww-data) ; In `eww.el' (Emacs 25+)
+(defvar eww-local-regex) ; In `eww.el' (Emacs 25+)
+(defvar eww-search-prefix) ; In `eww.el' (Emacs 25+)
+(defvar gnus-article-current) ; In `gnus-sum.el'
+(defvar icicle-candidate-properties-alist) ; In `icicles-var.el'
+(defvar icicle-completion-candidates) ; In `icicles-var.el'
+(defvar icicle-mode) ; In `icicle-mode.el'
+(defvar icicle-multi-completing-p) ; In `icicles-var.el'
+(defvar icicle-saved-completion-candidates) ; In `icicles-var.el'
+(defvar icicle-searching-p) ; In `icicles-var.el'
+(defvar Info-current-node) ; In `info.el'
+(defvar Info-current-file) ; In `info.el'
+(defvar kmacro-counter) ; In `kmacro.el'
+(defvar kmacro-counter-format-start) ; In `kmacro.el'
+(defvar kmacro-ring) ; In `kmacro.el'
+(defvar Man-arguments) ; In `man.el'
+(defvar org-store-link-functions) ; In `org.el'
+(defvar read-file-name-completion-ignore-case) ; Emacs 23+
+(defvar last-repeatable-command) ; In `repeat.el'
+(defvar w3m-current-title) ; In `w3m.el'
+(defvar w3m-current-url) ; In `w3m.el'
+(defvar w3m-mode-map) ; In `w3m.el'
+(defvar zz-izones) ; In `zones.el'
+(defvar zz-izones-var) ; In `zones.el'
+(defvar woman-last-file-name) ; In `woman.el'
+
+;;(@* "User Options (Customizable)")
+;;; User Options (Customizable) --------------------------------------
+
+;;;###autoload (autoload 'bmkp-autofile-access-invokes-bookmark-flag "bookmark+")
+(defcustom bmkp-autofile-access-invokes-bookmark-flag nil
+ "*Non-nil means invoke the bookmark when you access an autofile.
+That is, if a file has an associated autofile bookmark then functions
+such as `find-file' will automatically jump to the bookmark. The
+buffer position of an autofile bookmark is not important, but this can
+be useful to update the bookmark data, such as the number of visits.
+
+If you change the option value in Lisp code without using a Customize
+function, then add/remove `bmkp-find-file-invoke-bookmark-if-autofile'
+to/from `find-file-hook'."
+ :set (lambda (sym new-val)
+ (custom-set-default sym new-val)
+ (let ((hook-var (if (< emacs-major-version 22) 'find-file-hooks 'find-file-hook)))
+ (if bmkp-autofile-access-invokes-bookmark-flag
+ (add-hook hook-var 'bmkp-find-file-invoke-bookmark-if-autofile)
+ (remove-hook hook-var 'bmkp-find-file-invoke-bookmark-if-autofile))))
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-autofile-filecache "bookmark+")
+(defcustom bmkp-autofile-filecache 'cache-only
+ "*Whether Emacs filecache commands create/set an autofile bookmark.
+The possible values:
+`autofile+cache' - Whenever a file is added to the file cache, also
+ create/set an autofile bookmark for the file.
+`autofile-only' - Create/set an autofile instead of caching the file.
+`cache-only' - Add the file to the file cache. No autofile."
+ :type '(choice
+ (const :tag "Create/set an autofile bookmark instead of adding to file cache" autofile-only)
+ (const :tag "Create/set an autofile bookmark and add to file cache" autofile+cache)
+ (const :tag "Add to file cache only - do not create/set an autofile bookmark" cache-only))
+ :group 'bookmark-plus)
+
+
+;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+;; works for newer Emacs too.
+(when (fboundp 'defvaralias) ; Emacs 22+
+ (defvaralias 'bmkp-auto-idle-bookmark-min-distance 'bmkp-automatic-bookmark-min-distance)
+ (bmkp-make-obsolete-variable 'bmkp-auto-idle-bookmark-min-distance 'bmkp-automatic-bookmark-min-distance
+ "2021-08-18"))
+
+;;;###autoload (autoload 'bmkp-automatic-bookmark-min-distance "bookmark+")
+(defcustom bmkp-automatic-bookmark-min-distance 1000
+ "*Minimum number of chars between automatic bookmark positions.
+Automatic bookmarking is done by `bmkp-automatic-bookmark-mode'."
+ :type '(choice
+ (const :tag "No minumum distance" nil)
+ (integer :tag "At least this many chars" :value 1000))
+ :group 'bookmark-plus)
+
+;; Emacs 20 only.
+;;
+;; (Don't bother aliasing the old name, for Emacs 20.)
+;;
+;;;###autoload (autoload 'bmkp-automatic-bookmark-mode "bookmark+")
+(unless (fboundp 'define-minor-mode)
+ (defcustom bmkp-automatic-bookmark-mode nil
+ "*Non-nil means that bookmarks are created periodically automatically.
+Setting this variable directly does not take effect;
+use either \\[customize] or command `bmkp-automatic-bookmark-mode'."
+ :set (lambda (symbol value) (bmkp-automatic-bookmark-mode (if value 1 -1)))
+ :initialize 'custom-initialize-default
+ :type 'boolean :group 'bookmark-plus :require 'bookmark+))
+
+
+;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+;; works for newer Emacs too.
+(when (fboundp 'defvaralias) ; Emacs 22+
+ (defvaralias 'bmkp-auto-idle-bookmark-mode-delay 'bmkp-automatic-bookmark-mode-delay)
+ (bmkp-make-obsolete-variable 'bmkp-auto-idle-bookmark-mode-delay 'bmkp-automatic-bookmark-mode-delay
+ "2021-08-18"))
+
+;;;###autoload (autoload 'bmkp-automatic-bookmark-mode-delay "bookmark+")
+(defcustom bmkp-automatic-bookmark-mode-delay 60
+ "*Number of seconds delay before automatically setting a bookmark.
+Automatic bookmarking is done by `bmkp-automatic-bookmark-mode'."
+ :type 'integer :group 'bookmark-plus)
+
+
+;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+;; works for newer Emacs too.
+(when (fboundp 'defvaralias) ; Emacs 22+
+ (defvaralias 'bmkp-auto-idle-bookmark-mode-lighter 'bmkp-automatic-bookmark-mode-lighter)
+ (bmkp-make-obsolete-variable 'bmkp-auto-idle-bookmark-mode-lighter 'bmkp-automatic-bookmark-mode-lighter
+ "2021-08-18"))
+
+;;;###autoload (autoload 'bmkp-automatic-bookmark-mode-lighter "bookmark+")
+(defcustom bmkp-automatic-bookmark-mode-lighter " Auto-Bmk"
+ "*Lighter for `bmkp-automatic-bookmark-mode'.
+This string shows in the mode line when `bmkp-automatic-bookmark-mode'
+is enabled. Set this to nil or \"\" if you do not want any lighter."
+ :type 'string :group 'bookmark-plus)
+
+
+;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+;; works for newer Emacs too.
+(when (fboundp 'defvaralias) ; Emacs 22+
+ (defvaralias 'bmkp-auto-idle-bookmark-mode-set-function 'bmkp-automatic-bookmark-set-function)
+ (bmkp-make-obsolete-variable 'bmkp-auto-idle-bookmark-mode-set-function
+ 'bmkp-automatic-bookmark-set-function
+ "2021-08-18"))
+
+;;;###autoload (autoload 'bmkp-automatic-bookmark-set-function "bookmark+")
+(defcustom bmkp-automatic-bookmark-set-function #'bmkp-set-autonamed-bookmark-at-line
+ "*Function used to set an automatic bookmark.
+Used by `bmkp-automatic-bookmark-mode' and `bmkp-set-automatic-bookmark'.
+
+The default value, `bmkp-set-autonamed-bookmark-at-line', sets an
+autonamed bookmark at the start of the current line. To bookmark the
+current position, so you can have more than one automatic bookmark per
+line, use `bmkp-set-autonamed-bookmark' instead."
+ :type 'function :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-autoname-bookmark-function "bookmark+")
+(defcustom bmkp-autoname-bookmark-function 'bmkp-autoname-bookmark-function-default
+ "*Function to automatically name a bookmark at point (cursor position).
+It should accept a buffer position as its (first) argument.
+The name returned should match the application of
+`bmkp-autoname-format' to the buffer name."
+ :type 'function :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-autoname-format "bookmark+")
+(defcustom bmkp-autoname-format (if (> emacs-major-version 21) "^[0-9]\\{9\\} %B" "^[0-9]+ %B")
+ "*Format string to match an autonamed bookmark name.
+You can use `%B' instead of `%s' to accept the buffer name. This has
+the advantage that commands and other functions that check for a
+buffer-specific bookmark can tell more accurately whether a bookmark
+name matches the given buffer. This applies to functions such as
+`bmkp-autonamed-this-buffer-jump' and
+`bmkp-autonamed-this-buffer-bookmark-p'."
+ :type 'string :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-autotemp-bookmark-predicates "bookmark+")
+(defcustom bmkp-autotemp-bookmark-predicates '(bmkp-autonamed-bookmark-p
+ bmkp-autonamed-this-buffer-bookmark-p)
+ "*Predicates for bookmarks to be set (created) as temporary bookmarks.
+Each is typically a type predicate, but it can be any function that
+accepts as its (first) argument a bookmark or bookmark name.
+
+These are the predefined type predicates:
+
+`bmkp-annotated-bookmark-p', `bmkp-autofile-bookmark-p',
+`bmkp-autonamed-bookmark-for-buffer-p', `bmkp-autonamed-bookmark-p',
+`bmkp-autonamed-this-buffer-bookmark-p', `bmkp-buffer-bookmark-p',
+`bmkp-bookmark-file-bookmark-p', `bmkp-bookmark-list-bookmark-p',
+`bmkp-desktop-bookmark-p', `bmkp-dired-bookmark-p',
+`bmkp-dired-this-dir-bookmark-p', `bmkp-dired-wildcards-bookmark-p',
+`bmkp-eww-bookmark-p' (Emacs 25+), `bmkp-file-bookmark-p',
+`bmkp-file-remote-p', `bmkp-file-this-dir-bookmark-p',
+`bmkp-flagged-bookmark-p', `bmkp-function-bookmark-p',
+`bmkp-gnus-bookmark-p', `bmkp-icicles-search-hits-bookmark-p',
+`bmkp-image-bookmark-p', `bmkp-info-bookmark-p',
+`bmkp-last-specific-buffer-p', `bmkp-last-specific-file-p',
+`bmkp-local-directory-bookmark-p', `bmkp-local-file-bookmark-p',
+`bmkp-local-non-dir-file-bookmark-p', `bmkp-man-bookmark-p',
+`bmkp-marked-bookmark-p', `bmkp-modified-bookmark-p',
+`bmkp-navlist-bookmark-p', `bmkp-non-dir-file-bookmark-p',
+`bmkp-non-file-bookmark-p', `bmkp-non-invokable-bookmark-p',
+`bmkp-omitted-bookmark-p', `bmkp-orphaned-file-bookmark-p',
+`bmkp-orphaned-local-file-bookmark-p',
+`bmkp-orphaned-remote-file-bookmark-p', `bmkp-region-bookmark-p',
+`bmkp-remote-file-bookmark-p', `bmkp-remote-non-dir-file-bookmark-p',
+`bmkp-sequence-bookmark-p', `bmkp-snippet-bookmark-p',
+`bmkp-temporary-bookmark-p', `bmkp-this-buffer-p', `bmkp-this-file-p',
+`bmkp-url-bookmark-p', `bmkp-url-browse-bookmark-p',
+`bmkp-variable-list-bookmark-p', `bmkp-w3m-bookmark-p'"
+ :type '(repeat symbol) :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-bookmark-name-length-max "bookmark+")
+(defcustom bmkp-bookmark-name-length-max 70
+ "*Max number of chars for default name for a bookmark with a region."
+ :type 'integer :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-count-multi-mods-as-one-flag "bookmark+")
+(defcustom bmkp-count-multi-mods-as-one-flag t
+ "*Non-nil means count multiple modifications as one.
+This is for `bookmark-alist-modification-count'. Non-nil means that
+when you invoke a command that acts on multiple bookmarks or acts in
+multiple ways on one bookmark, all of changes together count as only
+one modification. That can prevent automatic saving of your bookmark
+file during the sequence of modifications, so that when the command is
+done you can choose not to save (i.e., to quit) if you like."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-crosshairs-flag "bookmark+")
+(defcustom bmkp-crosshairs-flag (> emacs-major-version 21)
+ "*Non-nil means highlight with crosshairs when you visit a bookmark.
+The highlighting is temporary - until your next action.
+You need library `crosshairs.el' for this feature, and you need Emacs
+22 or later.
+
+NOTE: Crosshairs highlighting is shown in the buffer that is current
+after jumping. If the bookmarked jumped to does not really have an
+associated buffer, for example a bookmark with a handler such as
+`w32-browser' that just invokes a separate, non-Emacs program, then
+the current buffer after jumping will be the buffer before jumping.
+
+If you use this option in Lisp code, you will want to add/remove
+`bmkp-crosshairs-highlight' to/from `bookmark-after-jump-hook'."
+ :set (lambda (sym new-val)
+ (custom-set-default sym new-val)
+ (if (and bmkp-crosshairs-flag (> emacs-major-version 21)
+ (condition-case nil (require 'crosshairs nil t) (error nil)))
+ (add-hook 'bookmark-after-jump-hook 'bmkp-crosshairs-highlight)
+ (remove-hook 'bookmark-after-jump-hook 'bmkp-crosshairs-highlight)))
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-default-bookmark-name "bookmark+")
+(defcustom bmkp-default-bookmark-name 'highlighted
+ "*Default bookmark name preference for accessing existing bookmarks.
+\(The default name for a *new* bookmark is obtained using option
+`bmkp-new-bookmark-default-names'.)
+
+In `*Bookmark List*' use the name of the current line's bookmark.
+Otherwise, if `bookmark+-lit.el' is not loaded then use the name of
+the last-used bookmark in the current file.
+
+Otherwise, use this option to determine the default, by preferring one
+of the following, if available:
+
+* a highlighted bookmark at point
+* the last-used bookmark in the current file"
+ :type '(choice
+ (const :tag "Highlighted bookmark at point" highlighted)
+ (const :tag "Last used bookmark in same file" last-used))
+ :group 'bookmark-plus)
+
+
+;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+;; works for newer Emacs too.
+(when (fboundp 'defvaralias) ; Emacs 22+
+ (defvaralias 'bmkp-default-handler-associations 'bmkp-default-handlers-for-file-types)
+ (bmkp-make-obsolete-variable 'bmkp-default-handler-associations 'bmkp-default-handlers-for-file-types
+ "2012-02-27"))
+
+;;;###autoload (autoload 'bmkp-default-handlers-for-file-types "bookmark+")
+(defcustom bmkp-default-handlers-for-file-types
+ (and (require 'dired-x) ; It in turn requires `dired-aux.el'
+ (eval-when-compile (when (< emacs-major-version 21) (require 'cl))) ;; `dolist', for Emacs 20
+ (let ((assns ()))
+ (dolist (shell-assn dired-guess-shell-alist-user)
+ (push (cons (car shell-assn)
+ `(lambda (bmk)
+ (dired-run-shell-command
+ (dired-shell-stuff-it ,(cadr shell-assn) (list (bookmark-get-filename bmk))
+ nil nil))))
+ assns))
+ assns))
+ "*File associations for bookmark handlers used for indirect bookmarks.
+Each element of the alist is (REGEXP . COMMAND).
+REGEXP matches a file name.
+COMMAND is a sexp that evaluates to either a shell command (a string)
+ or an Emacs function (a symbol or a lambda form). The shell command
+ or Lisp function must accept a file-name argument.
+
+Example value:
+
+ ((\"\\\\.pdf$\" . \"AcroRd32.exe\") ; Adobe Acrobat Reader
+ (\"\\\\.ps$\" . \"gsview32.exe\") ; Ghostview (PostScript viewer)
+ (\"\\\\.html?$\" . browse-url) ; Use Lisp function `browse-url'
+ (\"\\\\.doc$\" . w32-browser)) ; Use Lisp function `w32-browser'
+
+When you change this option using Customize, if you want to use a
+literal string as COMMAND then you must double-quote the text:
+\"...\". (But do not use double-quotes for the REGEXP.) If you want
+to use a symbol as COMMAND, just type the symbol name (no quotes).
+
+This option is used by `bmkp-default-handler-for-file' to determine
+the default `file-handler' property for a given file bookmark. If a
+given file name does not match this option, and if
+`bmkp-guess-default-handler-for-file-flag' is non-nil, then
+`bmkp-default-handler-for-file' tries to guess a shell command to use
+in the default handler. For that it uses `dired-guess-default' and
+\(Emacs 23+ only) mailcap entries, in that order."
+ :type '(alist :key-type
+ regexp :value-type
+ (sexp :tag "Shell command (string) or Emacs function (symbol or lambda form)"))
+ :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-desktop-default-directory "bookmark+")
+(defcustom bmkp-desktop-default-directory nil
+ "*Default directory used when reading the name of a desktop file.
+If nil then use the current directory (value of `default-directory')."
+ :type 'directory :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-desktop-jump-save-before-flag "bookmark+")
+(defcustom bmkp-desktop-jump-save-before-flag nil
+ "*Non-nil means `bmkp-desktop-jump' saves the desktop file before switching."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-desktop-no-save-vars "bookmark+")
+(defcustom bmkp-desktop-no-save-vars '(search-ring regexp-search-ring kill-ring)
+ "*List of variables not to save when creating a desktop bookmark.
+They are removed from `desktop-globals-to-save' for the duration of
+the save (only)."
+ :type '(repeat (variable :tag "Variable")) :group 'bookmark-plus)
+
+
+;; EWW support
+(when (> emacs-major-version 24) ; Emacs 25+
+
+ (defcustom bmkp-eww-auto-type 'update-only
+ "How `bmkp-eww-auto-bookmark-mode' behaves when enabled.
+You can toggle this option using `\\[bmkp-toggle-eww-auto-type]'."
+ :type '(choice
+ (const :tag "Create EWW bookmark or update existing EWW bookmark" create-or-update)
+ (const :tag "Update existing EWW bookmark (only)" update-only))
+ :group 'bookmark-plus)
+
+ ;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+ ;; works for newer Emacs too.
+ (defvaralias 'bmkp-eww-buffer-handling 'bmkp-eww-buffer-renaming)
+ (bmkp-make-obsolete-variable 'bmkp-eww-buffer-handling 'bmkp-eww-buffer-renaming "2018-02-23")
+
+ (defcustom bmkp-eww-buffer-renaming nil
+ "Whether and how an EWW buffer is renamed.
+Non-nil values affect EWW behavior even when bookmarks are not used.
+
+* nil: Do not rename buffer - use `*eww*' (vanilla EWW behavior).
+* `url': Rename buffer to web-page title plus last 20 chars of URL.
+* `page': Rename buffer to web-page title (only)."
+ :type '(choice
+ (const :tag "Do not rename buffer (use name `*eww*')" nil)
+ (const :tag "Rename buffer to web-page title plus last 20 chars of URL" url)
+ ;; Any symbol other than `page' and nil is treated the same as `page'.
+ (const :tag "Rename buffer to web-page title" page))
+ :group 'bookmark-plus)
+
+ (defcustom bmkp-eww-generate-buffer-flag nil
+ "Whether to generate a new buffer when jumping to an EWW bookmark.
+* nil means reuse an existing buffer for the bookmarked URL.
+* Non-nil means use a new buffer."
+ :type 'boolean :group 'bookmark-plus)
+
+ ;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+ ;; works for newer Emacs too.
+ (defvaralias 'bmkp-replace-eww-keys-flag 'bmkp-eww-replace-keys-flag)
+ (bmkp-make-obsolete-variable 'bmkp-replace-eww-keys-flag 'bmkp-eww-replace-keys-flag "2017-01-10")
+
+ (defcustom bmkp-eww-replace-keys-flag t
+ "Non-nil means replace EWW bookmarking keys and menus with Bookmark+ ones.
+If you change the value of this option then you must restart Emacs for
+it to take effect."
+ :type 'boolean :group 'bookmark-plus)
+ )
+
+;;;###autoload (autoload 'bmkp-annotation-modes-inherit-from "bookmark+")
+(defcustom bmkp-annotation-modes-inherit-from (if (fboundp 'org-mode) 'org-mode 'text-mode)
+ "Symbol for mode that bookmark annotation modes are to inherit from.
+Or nil if no parent mode. The annotation modes are
+`bmkp-edit-annotation-mode' and `bmkp-show-annotation-mode'.
+
+You must restart Emacs after changing the value of this option, for
+the change to take effect."
+ :type 'symbol :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-handle-region-function "bookmark+")
+(defcustom bmkp-handle-region-function 'bmkp-handle-region-default
+ "*Function to handle a bookmarked region."
+ :type 'function :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-info-sort-ignores-directories-flag "bookmark+")
+(defcustom bmkp-info-sort-ignores-directories-flag t
+ "*Non-nil means Info-bookmark sorting uses manual names, not file locations.
+If nil, the absolute file names of the manuals are used. This can be
+useful if you have bookmarks for multiple Emacs releases, and you want
+the bookmarks for a given release to appear together."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-incremental-filter-delay "bookmark+")
+(defcustom bmkp-incremental-filter-delay (if (boundp 'bookmark-search-delay)
+ bookmark-search-delay
+ 0.2)
+ "*Seconds to wait before updating display when filtering bookmarks."
+ :type 'number :group 'bookmark-plus)
+
+
+(when (> emacs-major-version 21) ; Emacs 22+ (need also `Info-selection-hook').
+
+ (defcustom bmkp-info-auto-type 'create-or-update
+ "How `bmkp-info-auto-bookmark-mode' behaves when enabled.
+You can toggle this option using `\\[bmkp-toggle-info-auto-type]'."
+ :type '(choice
+ (const :tag "Create Info bookmark or update existing Info bookmark" create-or-update)
+ (const :tag "Update existing Info bookmark (only)" update-only))
+ :group 'bookmark-plus)
+
+ )
+
+;; Removed autoload cookie, to avoid (void-variable bookmark-default-file) ;;;###autoload
+(defcustom bmkp-last-as-first-bookmark-file bookmark-default-file
+ "*Whether to use the last-used bookmark file as the first used.
+If nil then Emacs always uses the value of `bookmark-default-file' as
+the initial bookmark file, in any given session.
+
+If non-nil, Emacs uses the last bookmark file you used, in the last
+Emacs session. If none was recorded then it uses
+`bookmark-default-file'. The particular non-nil value must be an
+absolute file name \(possibly containing `~') - it is not expanded).
+
+NOTE: A non-nil option value is overwritten by Bookmark+, so that it
+becomes the last-used bookmark file. A nil value is never
+overwritten."
+ :type '(choice
+ (const :tag "Use `bookmark-default-file' as initial bookmark file" nil)
+ (file :tag "Use last-used bookmark file as initial bookmark file"
+ :value "~/.emacs.bmk"))
+ :group 'bookmark)
+
+;;;###autoload (autoload 'bmkp-menu-popup-max-length "bookmark+")
+(defcustom bmkp-menu-popup-max-length 20
+ "*Max number of bookmarks for `bookmark-completing-read' to use a menu.
+When choosing a bookmark from a list of bookmarks using
+`bookmark-completing-read', this controls whether to use a menu or
+minibuffer input with completion.
+If t, then always use a menu.
+If nil, then never use a menu.
+If an integer, then use a menu only if there are fewer bookmark
+ choices than the value."
+ :type '(choice
+ (integer :tag "Use a menu if there are fewer bookmark choices than this" 20)
+ (const :tag "Always use a menu to choose a bookmark" t)
+ (const :tag "Never use a menu to choose a bookmark" nil))
+ :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-new-bookmark-default-names "bookmark+")
+(defcustom bmkp-new-bookmark-default-names
+ (let ((fns '((lambda () (let ((ff (function-called-at-point)))
+ (and ff (symbolp ff) (symbol-name ff)))))))
+ (when (fboundp 'region-or-non-nil-symbol-name-nearest-point) ; Defined in `thingatpt+.el'.
+ (setq fns (cons 'region-or-non-nil-symbol-name-nearest-point fns)))
+ fns)
+ "Functions to produce the default name for a new bookmark.
+\(The default name for an *existing* bookmark is obtained using
+`bmkp-default-bookmark-name'.)
+
+The option value is a list of functions that do not require an
+argument and return a string (or nil). They are invoked, in order, to
+produce the default names.
+
+The following names are also provided, after the names described
+above: The value of variable `bookmark-current-bookmark' and the
+return value of function `bookmark-buffer-name', in that order.
+
+These latter names are the defaults provided by vanilla Emacs
+`bookmark.el', so if you want the vanilla behavior then set the option
+value to nil.
+
+For non-interactive use of a default bookmark name, and for Emacs
+prior to Emacs 23 even for interactive use, only the first default
+name is used.
+
+Some functions you might want to use in the option value:
+
+ * `region-or-non-nil-symbol-name-nearest-point'
+ * (lambda () (let ((ff (function-called-at-point)))
+ (and (symbolp ff) (symbol-name ff))))
+ * (lambda () (let ((vv (variable-at-point))) ; `variable-at-point'
+ (and (symbolp vv) (symbol-name vv)))) ; returns 0 if no var
+ * `word-at-point'
+ * (lambda () (let ((ss (symbol-at-point)))
+ (and ss (symbol-name ss))))
+
+The first of these is defined in library `thingatpt+.el'. It returns
+the text in the region, if it is active and not empty. Otherwise it
+returns the name of the (non-`nil') symbol nearest point, within
+maximum search distances `tap-near-point-x-distance' (left and right)
+and `tap-near-point-y-distance' (up and down)."
+ :type '(repeat function) :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-other-window-pop-to-flag "bookmark+")
+(defcustom bmkp-other-window-pop-to-flag t
+ "*Non-nil means other-window bookmark jumping uses `pop-to-buffer'.
+Use nil if you want the vanilla Emacs behavior, which uses
+`switch-to-buffer-other-window'. That creates a new window even if
+there is already another window showing the buffer."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-prompt-for-tags-flag "bookmark+")
+(defcustom bmkp-prompt-for-tags-flag nil
+ "*Non-nil means setting bookmarks interactively prompts for tags to add.
+For an existing bookmark, if option `bmkp-properties-to-keep' includes
+`tags' (which it does by default), then the tags you enter are added
+to any that the bookmark already has - none are removed."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-properties-to-keep "bookmark+")
+(defcustom bmkp-properties-to-keep '(tags annotation)
+ "*List of properties to keep when you set an existing bookmark.
+When you set a bookmark that already exists, its properties are
+updated (overwritten), with the exception of those listed here."
+ :type '(repeat symbol) :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-region-search-size "bookmark+")
+(defcustom bmkp-region-search-size 40
+ "*Same as `bookmark-search-size', but specialized for bookmark regions."
+ :type 'integer :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-save-new-location-flag "bookmark+")
+(defcustom bmkp-save-new-location-flag t
+ "*Non-nil means save automatically relocated bookmarks.
+If nil, then the new bookmark location is visited, but it is not saved
+as part of the bookmark definition."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-sequence-jump-display-function "bookmark+")
+(defcustom bmkp-sequence-jump-display-function 'pop-to-buffer
+ "*Function used to display the bookmarks in a bookmark sequence."
+ :type 'function :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-show-end-of-region-flag "bookmark+")
+(defcustom bmkp-show-end-of-region-flag t
+ "*Show end of region with `exchange-point-and-mark' when activating a region.
+If nil show only beginning of region."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-sort-comparer "bookmark+")
+(defcustom bmkp-sort-comparer '((bmkp-info-node-name-cp bmkp-gnus-cp bmkp-url-cp bmkp-local-file-type-cp)
+ bmkp-alpha-p) ; This corresponds to `s k'.
+ ;; $$$$$$ An alternative default value: `bmkp-alpha-p', which corresponds to `s n'.
+ "*Predicate or predicates for sorting (comparing) bookmarks.
+This defines the default sort for bookmarks in the bookmark list.
+
+Various sorting commands, such as \\<bookmark-bmenu-mode-map>\
+`\\[bmkp-bmenu-sort-by-bookmark-visit-frequency]', change the value of this
+option dynamically (but they do not save the changed value).
+
+The value must be one of the following:
+
+* nil, meaning do not sort
+
+* a predicate that takes two bookmarks as args
+
+* a list of the form ((PRED...) FINAL-PRED), where each PRED and
+ FINAL-PRED are predicates that take two bookmarks as args
+
+If the value is a list of predicates, then each PRED is tried in turn
+until one returns a non-nil value. In that case, the result is the
+car of that value. If no non-nil value is returned by any PRED, then
+FINAL-PRED is used and its value is the result.
+
+Each PRED should return `(t)' for true, `(nil)' for false, or nil for
+undecided. A nil value means that the next PRED decides (or
+FINAL-PRED, if there is no next PRED).
+
+Thus, a PRED is a special kind of predicate that indicates either a
+boolean value (as a singleton list) or \"I cannot decide - let the
+next guy else decide\". (Essentially, each PRED is a hook function
+that is run using `run-hook-with-args-until-success'.)
+
+Examples:
+
+ nil - No sorting.
+
+ string-lessp - Single predicate that returns nil or non-nil.
+
+ ((p1 p2)) - Two predicates `p1' and `p2', which each return
+ (t) for true, (nil) for false, or nil for undecided.
+
+ ((p1 p2) string-lessp)
+ - Same as previous, except if both `p1' and `p2' return
+ nil, then the return value of `string-lessp' is used.
+
+Note that these two values are generally equivalent, in terms of their
+effect (*):
+
+ ((p1 p2))
+ ((p1) p2-plain) where p2-plain is (bmkp-make-plain-predicate p2)
+
+Likewise, these three values generally act equivalently (*):
+
+ ((p1))
+ (() p1-plain)
+ p1-plain where p1-plain is (bmkp-make-plain-predicate p1)
+
+The PRED form lets you easily combine predicates: use `p1' unless it
+cannot decide, in which case try `p2', and so on. The value ((p2 p1))
+tries the predicates in the opposite order: first `p2', then `p1' if
+`p2' returns nil.
+
+Using a single predicate or FINAL-PRED makes it easy to reuse an
+existing predicate that returns nil or non-nil.
+
+You can also convert a PRED-type predicate (which returns (t), (nil),
+or nil) into an ordinary predicate, by using function
+`bmkp-make-plain-predicate'. That lets you reuse elsewhere, as
+ordinary predicates, any PRED-type predicates you define.
+
+For example, this defines a plain predicate to compare by URL:
+ (defalias 'bmkp-url-p (bmkp-make-plain-predicate 'bmkp-url-cp))
+
+Note: As a convention, predefined Bookmark+ PRED-type predicate names
+have the suffix `-cp' (for \"component predicate\") instead of `-p'.
+
+--
+* If you use `\\[bmkp-reverse-multi-sort-order]', then there is a difference in \
+behavior between
+
+ (a) using a plain predicate as FINAL-PRED and
+ (b) using the analogous PRED-type predicate (and no FINAL-PRED).
+
+ In the latter case, `\\[bmkp-reverse-multi-sort-order]' affects when the predicate \
+is tried and
+ its return value. See `bmkp-reverse-multi-sort-order'."
+ :type '(choice
+ (const :tag "None (do not sort)" nil)
+ (function :tag "Sorting Predicate")
+ (list :tag "Sorting Multi-Predicate"
+ (repeat (function :tag "Component Predicate"))
+ (choice
+ (const :tag "None" nil)
+ (function :tag "Final Predicate"))))
+ :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-su-or-sudo-regexp "bookmark+")
+(defcustom bmkp-su-or-sudo-regexp "\\(/su:\\|/sudo:\\)"
+ "*Regexp to recognize `su' or `sudo' Tramp bookmarks."
+ :type 'regexp :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-tags-for-completion "bookmark+")
+(defcustom bmkp-tags-for-completion 'current
+ "*List of strings used as tags for completion (not an alist).
+The tags can be specified here individually or taken from (a) the
+current bookmark list or (b) one or more bookmark files or both.
+
+\(In Emacs 20 and 21, you cannot choose (b) when customizing, but if
+\(b) was chosen using a later Emacs version then the option value can
+still be used in Emacs 20 and 21.)
+
+If a relative file name is specified for a bookmark file then the
+current value of `default-directory' is used to find the file."
+ :type (if (> emacs-major-version 21)
+ '(choice
+ (const :tag "From current bookmarks only" current)
+ (list :tag "From current bookmarks and other sources"
+ (const :tag "" current)
+ (repeat :inline t :tag "Additional sources or specific tags"
+ (choice
+ (string :tag "Specific tag")
+ (cons :tag "All tags from a bookmark file"
+ (const :tag "" bmkfile) (file :must-match t)))))
+ (repeat :tag "Choose sources or specific tags"
+ (choice
+ (string :tag "Specific tag")
+ (cons :tag "All tags from a bookmark file"
+ (const :tag "" bmkfile) (file :must-match t)))))
+ ;; A bug in Emacs 20-21 means we must sacrifice the user choice of current plus other sources.
+ '(choice
+ (const :tag "From current bookmarks only" current)
+ (repeat :tag "Choose sources or specific tags" ; A 2nd Emacs 20-21 bug ignores `:tag' for menu.
+ (choice
+ (string :tag "Specific tag")
+ (cons :tag "All tags from a bookmark file"
+ (const :tag "" bmkfile) (file :must-match t))))))
+ :group 'bookmark-plus)
+
+;; Emacs 20 only.
+(unless (fboundp 'define-minor-mode)
+ (defcustom bmkp-temporary-bookmarking-mode nil
+ "*Non-nil means that bookmarks are temporary (not recorded on disk).
+Setting this variable directly does not take effect;
+use either \\[customize] or command `bmkp-temporary-bookmarking-mode'."
+ :set (lambda (symbol value) (bmkp-temporary-bookmarking-mode (if value 1 -1)))
+ :initialize 'custom-initialize-default
+ :type 'boolean :group 'bookmark-plus :require 'bookmark+))
+
+;;;###autoload (autoload 'bmkp-temporary-bookmarking-mode-hook "bookmark+")
+(defcustom bmkp-temporary-bookmarking-mode-hook ()
+ "*Functions run after entering and exiting temporary-bookmarking mode."
+ :type 'hook :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-this-file/buffer-cycle-sort-comparer "bookmark+")
+(defcustom bmkp-this-file/buffer-cycle-sort-comparer '((bmkp-position-cp))
+ "*`bmkp-sort-comparer' value for cycling this-file/buffer bookmarks.
+Use bookmarks for the currently visited file or (non-file) buffer.
+Some values you might want to use: ((bmkp-position-cp)),
+ ((bmkp-bookmark-creation-cp)), ((bmkp-visited-more-cp)).
+See `bmkp-sort-comparer'."
+ :type '(choice
+ (const :tag "None (do not sort)" nil)
+ (function :tag "Sorting Predicate")
+ (list :tag "Sorting Multi-Predicate"
+ (repeat (function :tag "Component Predicate"))
+ (choice
+ (const :tag "None" nil)
+ (function :tag "Final Predicate"))))
+ :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-guess-default-handler-for-file-flag "bookmark+")
+(defcustom bmkp-guess-default-handler-for-file-flag nil
+ "*Non-nil means guess the default handler when creating a file bookmark.
+This is ignored if a handler can be found using option
+`bmkp-default-handlers-for-file-types'. Otherwise, this is used by
+function `bmkp-default-handler-for-file' to determine the default
+handler for a given file."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-read-bookmark-file-hook "bookmark+")
+(defcustom bmkp-read-bookmark-file-hook ()
+ "*List of functions called, in order, after reading a bookmark file.
+Each function should accept the list of bookmarks read from the file
+as first argument and the bookmark file name as second argument."
+ :type 'hook :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-temporary-bookmarking-mode-lighter "bookmark+")
+(defcustom bmkp-temporary-bookmarking-mode-lighter " Temp-Bmk"
+ "*Lighter for `bmkp-temporary-bookmarking-mode'.
+This string shows in the mode line when `bmkp-temporary-bookmarking-mode'
+is enabled. Set this to nil or \"\" if you do not want any lighter."
+ :type 'string :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-use-region "bookmark+")
+(defcustom bmkp-use-region t
+ "*Non-nil means visiting a bookmark activates its recorded region."
+ :type '(choice
+ (const :tag "Activate bookmark region (except during cycling)" t)
+ (const :tag "Do not activate bookmark region" nil)
+ (const :tag "Activate bookmark region even during cycling" cycling-too))
+ :group 'bookmark-plus)
+
+;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+;; works for newer Emacs too.
+;;;###autoload (autoload 'bmkp-w3m-allow-multiple-buffers-flag "bookmark+")
+(when (fboundp 'defvaralias) ; Emacs 22+
+ (defvaralias 'bmkp-w3m-allow-multi-tabs-flag 'bmkp-w3m-allow-multiple-buffers-flag))
+(bmkp-make-obsolete-variable 'bmkp-w3m-allow-multi-tabs-flag 'bmkp-w3m-allow-multiple-buffers-flag
+ "2017-01-10")
+
+(defcustom bmkp-w3m-allow-multiple-buffers-flag t
+ "*Non-nil means jump to a W3M bookmark in a new buffer."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-write-bookmark-file-hook "bookmark+")
+(defcustom bmkp-write-bookmark-file-hook ()
+ "*List of functions called, in order, after writing a bookmark file.
+Each function should accept the bookmark file name as first argument.
+Used after `after-save-hook'."
+ :type 'hook :group 'bookmark-plus)
+
+;; This and the version of function `Info-bookmark-jump' defined here are also defined in `info+.el',
+;; so that their feature is available if you use either `Info+' or `Bookmark+'.
+;;
+;;;###autoload
+(defcustom Info-bookmark-use-only-node-not-file-flag t
+ "Non-nil means an Info bookmark uses only the node name.
+The recorded Info file name is ignored. This means use only manuals
+corresponding to the current Emacs session, regardless of the Emacs
+version or platform used to record the bookmark.
+
+A nil value means use the manuals whose absolute file names are
+recorded in the bookmarks. (But if the file doesn't exist or is
+unreadable, then act as if the value is non-nil.)
+
+A non-nil value means you can use the same bookmark with different
+Emacs installations, including on different platforms. A nil value
+means that you can use a bookmark to consult the Info manual for a
+different Emacs version from that of the current session."
+ :type 'boolean :group 'bookmark-plus)
+
+;;(@* "Internal Variables")
+;;; Internal Variables -----------------------------------------------
+
+(defconst bmkp-non-file-filename " - no file -"
+ "Name to use for `filename' entry, for non-file bookmarks.")
+
+(defvar bmkp-after-set-hook nil "Hook run after `bookmark-set' sets a bookmark.")
+
+(defvar bmkp-automatic-bookmarks ()
+ "Alist of bookmarks that were created automatically during this session.")
+
+
+;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
+;; works for newer Emacs too.
+(when (fboundp 'defvaralias) ; Emacs 22+
+ (defvaralias 'bmkp-automatic-bookmark-mode-timer 'bmkp-auto-idle-bookmark-mode-timer)
+ (bmkp-make-obsolete-variable 'bmkp-auto-idle-bookmark-mode-timer 'bmkp-automatic-bookmark-mode-timer
+ "2021-08-18"))
+
+(defvar bmkp-automatic-bookmark-mode-timer nil
+ "Timer for `bmkp-automatic-bookmark-mode'.
+This variable is buffer-local, which means that there is a separate
+timer for each buffer where automatic bookmarking is enabled.
+
+NOTE: For Emacs 20, the variable is not buffer-local, by default. To
+make it so, do this:
+
+ (make-variable-buffer-local 'bmkp-automatic-bookmark-mode-timer)")
+
+(unless (< emacs-major-version 21) (make-variable-buffer-local 'bmkp-automatic-bookmark-mode-timer))
+
+
+(defvar bmkp-autotemp-all-when-set-p nil "Non-nil means make any bookmark temporary whenever it is set.")
+
+;;; $$$$$$ No - don't bother.
+;;; (defconst bmkp-bookmark-modifier-functions '(bookmark-prop-set bmkp-replace-existing-bookmark
+;;; bookmark-set-name bookmark-store)
+;;; "List of functions that modify bookmarks.
+;;; Used to mark modified, unsaved bookmarks, in `*Bookmark List*'.
+;;; Should not include any function that calls another in the list.")
+
+
+;; `defvar' Provided for older Emacs versions.
+(defvar bookmark-after-jump-hook nil
+ "Hook run after `bookmark-jump' jumps to a bookmark.
+Useful for example to unhide text in `outline-mode'.")
+
+(defvar bmkp-before-jump-hook nil
+ "Hook run before `bookmark-jump' jumps to a bookmark.")
+
+(defvar bmkp-copied-tags ()
+ "List of tags copied from a bookmark, for pasting to other bookmarks.")
+
+(defvar bmkp-bookmark-set-confirms-overwrite-p nil
+ "Non-nil means `bookmark-set' requires confirmation about overwriting.")
+
+(defvar bmkp-current-bookmark-file bookmark-default-file
+ "Current bookmark file.
+When you start Emacs, this is initialized according to
+`bmkp-last-as-first-bookmark-file'.
+
+When you load bookmarks using `\\[bmkp-switch-bookmark-file-create]', this is set to the file you
+load. When you save bookmarks using `bookmark-save' with no prefix
+arg, they are saved to this file.
+
+Loading a bookmark file does not change the value of
+`bookmark-default-file', but it might change the value of
+`bmkp-last-as-first-bookmark-file' (which see). The value of
+`bookmark-default-file' is never changed, except by your
+customizations.")
+
+(defvar bmkp-desktop-current-file nil
+ "Desktop file from last desktop bookmark jumped to.")
+
+(defvar bmkp-edit-bookmark-orig-record nil
+ "Record of bookmark being edited.")
+
+(defvar bmkp-ffap-max-region-size 1024 ; See also Emacs bug #25243.
+ "Max size of active region used to obtain file-name defaults.
+An active region larger than this many characters prevents
+`bmkp-ffap-guesser' from calling `ffap-guesser'.")
+
+(defvar bmkp-file-bookmark-handlers '(bmkp-jump-dired image-bookmark-jump)
+ "List of functions that handle file or directory bookmarks.
+This is used to determine `bmkp-file-bookmark-p'.")
+
+(defvar bmkp-icicles-search-hits-retrieve-more nil
+ "Non-nil means add hits recorded in bookmark to current search hits.
+Otherwise, replace current with bookmark hits.")
+
+(defvar bmkp-last-bmenu-state-file nil "Last value of option `bmkp-bmenu-state-file'.")
+
+(defvar bmkp-last-bookmark-file bookmark-default-file
+ "Last bookmark file used in this session (or default bookmark file).
+This is a backup for `bmkp-current-bookmark-file'.")
+
+(defvar bmkp-current-nav-bookmark nil "Current bookmark for navigation.")
+
+(defvar bmkp-jump-display-function nil "Function used currently to display a bookmark.")
+
+(defvar bmkp-last-specific-buffer ""
+ "Name of buffer used by `bmkp-last-specific-buffer-p'.")
+
+(defvar bmkp-last-specific-file ""
+ "(Absolute) file name used by `bmkp-last-specific-file-p'.")
+
+(defvar bmkp-modified-bookmarks ()
+ "Alist of bookmarks that have been modified and not saved.")
+
+(defvar bmkp-nav-alist () "Current bookmark alist used for navigation.")
+
+(defvar bmkp-return-buffer nil "Name of buffer to return to.")
+
+(defvar bmkp-reverse-sort-p nil "Non-nil means the sort direction is reversed.")
+
+(defvar bmkp-reverse-multi-sort-p nil
+ "Non-nil means the truth values returned by predicates are complemented.
+This changes the order of the sorting groups, but it does not in
+general reverse that order. The order within each group is unchanged
+\(not reversed).")
+
+(defvar bmkp-use-w32-browser-p nil
+ "Non-nil means use `w32-browser' in the default bookmark handler.
+That is, use the default Windows application for the bookmarked file.
+This has no effect if function `w32-browser' is not defined.")
+
+(defvar bmkp-latest-bookmark-alist () "Copy of `bookmark-alist' as last filtered.")
+
+(defvar bmkp-last-save-flag-value nil "Last value of option `bookmark-save-flag'.")
+
+(defvar bmkp-sorted-alist ()
+ "Copy of current bookmark alist, as sorted for buffer `*Bookmark List*'.
+Has the same structure as `bookmark-alist'.")
+
+(defvar bmkp-tag-history () "History of tags read from the user.")
+
+(defvar bmkp-tags-alist ()
+ "Alist of all bookmark tags, per option `bmkp-tags-for-completion'.
+Each entry is a full tag: a cons whose car is a tag name, a string.
+This is set by function `bmkp-tags-list'.
+Use that function to update the value.")
+
+
+;; REPLACES ORIGINAL DOC STRING in `bookmark.el'.
+;;
+;; Doc string does not say that the file that was loaded is `bookmark-default-file'.
+;;
+(defvar bookmarks-already-loaded nil
+ "Non-nil means some bookmarks have been loaded during this Emacs session.")
+
+
+;; REPLACES ORIGINAL DOC STRING in `bookmark.el'.
+;;
+;; Doc string reflects `Bookmark+' enhancements.
+;;
+(put 'bookmark-alist 'variable-documentation
+ "Current list of bookmarks (bookmark records).
+Bookmark functions update the value automatically.
+You probably do not want to change the value yourself.
+
+The value is an alist with entries of the form
+ (BOOKMARK-NAME . PARAM-ALIST)
+or the deprecated form (BOOKMARK-NAME PARAM-ALIST).
+
+ BOOKMARK-NAME is the name you gave to the bookmark when creating it.
+ PARAM-ALIST is an alist of bookmark data. The order of the entries
+ in PARAM-ALIST is not important. The possible entries are described
+ below.
+
+Bookmarks created using vanilla Emacs (`bookmark.el'):
+
+ (filename . FILENAME)
+ (location . LOCATION)
+ (position . POS)
+ (front-context-string . STR-AFTER-POS)
+ (rear-context-string . STR-BEFORE-POS)
+ (handler . HANDLER)
+ (annotation . ANNOTATION)
+
+ FILENAME names the bookmarked file.
+ LOCATION names the bookmarked file, URL, or other place (Emacs 23+).
+ FILENAME or LOCATION is what is shown in the bookmark list
+ (`C-x r l') when you use `M-t'.
+ POS is the bookmarked buffer position (position in the file).
+ STR-AFTER-POS is buffer text that immediately follows POS.
+ STR-BEFORE-POS is buffer text that immediately precedes POS.
+ ANNOTATION is a string that you can provide to identify the bookmark.
+ See options `bookmark-use-annotations' and
+ `bookmark-automatically-show-annotations'.
+ HANDLER is a function that provides the bookmark-jump behavior
+ for a specific kind of bookmark. This is the case for Info
+ bookmarks, for instance (starting with Emacs 23).
+
+Bookmarks created using Bookmark+ are the same as for vanilla Emacs,
+except for the following differences.
+
+1. Visit information is recorded, using entries `visits' and `time':
+
+ (visits . NUMBER-OF-VISITS)
+ (time . TIME-LAST-VISITED)
+
+ NUMBER-OF-VISITS is a whole-number counter.
+
+ TIME-LAST-VISITED is an Emacs time representation, such as is
+ returned by function `current-time'.
+
+2. The buffer name is recorded, using entry `buffer-name'. It need
+not be associated with a file.
+
+3. If no file is associated with the bookmark, then FILENAME is
+ ` - no file -'.
+
+4. Bookmarks can be tagged by users. The tag information is recorded
+using entry `tags':
+
+ (tags . TAGS-ALIST)
+
+ TAGS-ALIST is an alist with string keys.
+
+5. A bookmark can be simply a wrapper for a file, in which case it has
+entry `file-handler' instead of `handler'. When you \"jump\" to such
+a bookmark, the `file-handler' function or shell-command is applied to
+the `filename' entry. Any `handler' entry present is ignored, as are
+entries such as `position'. It is only the target file that is
+important.
+
+6. Bookmarks can have individual highlighting, provided by users.
+This overrides any default highlighting.
+
+ (lighting . HIGHLIGHTING)
+
+ HIGHLIGHTING is a property list that contain any of these keyword
+ pairs:
+
+ `:style' - Highlighting style. Cdrs of `bmkp-light-styles-alist'
+ entries are the possible values.
+ `:face' - Highlighting face, a symbol.
+ `:when' - A sexp to be evaluated. Return value of `:no-light'
+ means do not highlight.
+
+7. The following additional entries are used to record region
+information. When a region is bookmarked, POS represents the region
+start position.
+
+ (end-position . END-POS)
+ (front-context-region-string . STR-BEFORE-END-POS)
+ (rear-context-region-string . STR-AFTER-END-POS))
+
+ END-POS is the region end position.
+ STR-BEFORE-END-POS is buffer text that precedes END-POS.
+ STR-AFTER-END-POS is buffer text that follows END-POS.
+
+The two context region strings are non-nil only when a region is
+bookmarked.
+
+ NOTE: The relative locations of `front-context-region-string' and
+ `rear-context-region-string' are reversed from those of
+ `front-context-string' and `rear-context-string'. For example,
+ `front-context-string' is the text that *follows* `position', but
+ `front-context-region-string' *precedes* `end-position'.
+
+8. The following additional entries are used for a Dired bookmark.
+
+ (dired-marked . MARKED-FILES)
+ (dired-subdirs . INSERTED-SUBDIRS)
+ (dired-hidden-dirs . HIDDEN-SUBDIRS)
+ (dired-switches . SWITCHES)
+
+ MARKED-FILES is the list of files that were marked `*'.
+ INSERTED-SUBDIRS is the list of subdirectores that were inserted.
+ HIDDEN-SUBDIRS is the list of inserted subdirs that were hidden.
+ SWITCHES is the string of `dired-listing-switches'.
+
+9. The following additional entries are used for a Gnus bookmark.
+
+ (group . GNUS-GROUP-NAME)
+ (article . GNUS-ARTICLE-NUMBER)
+ (message-id . GNUS-MESSAGE-ID)
+
+ GNUS-GROUP-NAME is the name of a Gnus group.
+ GNUS-ARTICLE-NUMBER is the number of a Gnus article.
+ GNUS-MESSAGE-ID is the identifier of a Gnus message.
+
+10. For a URL bookmark, FILENAME or LOCATION is a URL.
+
+11. A sequence bookmark has this additional entry:
+
+ (sequence . COMPONENT-BOOKMARKS)
+
+ COMPONENT-BOOKMARKS is the list of component bookmark names.
+
+12. A function bookmark has this additional entry, which records the
+FUNCTION:
+
+ (function . FUNCTION)
+
+13. A bookmark-list bookmark has this additional entry, which records
+the state of buffer `*Bookmark List*' at the time it is created:
+
+ (bookmark-list . STATE)
+
+ STATE records the sort order, filter function, omit list, and title.")
+
+;;(@* "Compatibility Code for Older Emacs Versions")
+;;; Compatibility Code for Older Emacs Versions ----------------------
+
+(when (< emacs-major-version 23)
+
+ ;; These definitions are for Emacs versions prior to Emacs 23.
+ ;; They are the same as the vanilla Emacs 24+ definitions, except as noted.
+ ;; They let older versions of Emacs handle bookmarks created with Emacs 23+.
+ ;; (Emacs < 23 also needs a compatible `bookmark-make-record' version,
+ ;; but I redefine it for all versions, in any case.)
+
+ (defun Info-bookmark-make-record ()
+ "Create a bookmark record for the current Info node (and point).
+Implements `bookmark-make-record-function' for Info nodes."
+ (let* ((file (and (stringp Info-current-file) (file-name-nondirectory Info-current-file)))
+ (bookmark-name (if file
+ (concat "(" file ") " Info-current-node)
+ Info-current-node))
+ (defaults (delq nil (list bookmark-name file Info-current-node))))
+ `(,bookmark-name
+ ,@(bookmark-make-record-default 'NO-FILE)
+ (filename . ,Info-current-file)
+ (info-node . ,Info-current-node)
+ (handler . Info-bookmark-jump)
+ (defaults . ,defaults))))
+
+ (add-hook 'Info-mode-hook (lambda () (set (make-local-variable 'bookmark-make-record-function)
+ 'Info-bookmark-make-record)))
+
+ (defvar bookmark-make-record-function 'bookmark-make-record-default
+ "Function called with no arguments, to create a bookmark record.
+Modes can set this buffer-locally to enable bookmarking of locations
+that should be treated specially for the mode. Global commands can
+bind this and then create a bookmark, to get special treatment
+anywhere.
+
+The function value should return a new bookmark record, which should
+be a cons cell of the form (NAME . ALIST) or just ALIST, where ALIST
+is as described in `bookmark-alist'. If it cannot construct the
+record, then it should raise an error.
+
+NAME is a string that names the new bookmark. NAME can be nil, in
+which case a default name is used.
+
+ALIST can contain an entry (handler . FUNCTION) which sets the handler
+to FUNCTION, which is then used instead of `bookmark-default-handler'.
+FUNCTION must accept the same arguments as `bookmark-default-handler'.")
+
+ (defun bookmark-prop-get (bookmark prop)
+ "Return entry (property) PROP of BOOKMARK, or nil if no such entry.
+BOOKMARK is a bookmark name or a bookmark record."
+ (cdr (assq prop (bmkp-bookmark-data-from-record bookmark))))
+
+ (defun bookmark-get-handler (bookmark)
+ "Return the `handler' entry for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+ (bookmark-prop-get bookmark 'handler))
+
+ (defun bookmark-jump-noselect (bookmark)
+ "Return the location recorded for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+The return value has the form (BUFFER . POINT), where BUFFER is a
+buffer and POINT is the location within BUFFER."
+ (save-excursion (bookmark-handle-bookmark bookmark) (cons (current-buffer) (point)))))
+
+(when (< emacs-major-version 22)
+
+ ;; These definitions are for Emacs versions prior to Emacs 22.
+ ;; They are the same as the vanilla Emacs 22+ definitions, except as noted.
+
+;;; ;; Bookmark+ doesn't use this, but `bookmark.el' still does. Who has a slow `baud-rate' now?
+;;; (defun bookmark-maybe-message (fmt &rest args)
+;;; "Apply `message' to FMT and ARGS, but only if the display is fast enough."
+;;; (when (>= baud-rate 9600) (apply 'message fmt args)))
+
+ ;; Emacs 22+ just uses `bookmark-jump-other-window' for the menu also.
+ (defun bmkp-menu-jump-other-window (event)
+ "Jump to BOOKMARK (a point in some file) in another window.
+See `bookmark-jump-other-window'."
+ (interactive "e")
+ (bookmark-popup-menu-and-apply-function 'bookmark-jump-other-window
+ "Jump to Bookmark (Other Window)" event)))
+
+;;(@* "Core Replacements (`bookmark-*' except `bookmark-bmenu-*')")
+;;; Core Replacements (`bookmark-*' except `bookmark-bmenu-*') -------
+
+
+
+;; REPLACES DOCUMENTATION of ORIGINAL in `bookmark.el'.
+;;
+;; Doc now just says that this option is ignored by Bookmark+.
+(put 'bookmark-sort-flag 'variable-documentation
+ "Ignored by Bookmark+, which uses option `bmkp-sort-comparer' instead.")
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Changed default value to t.
+;; Added `:tag' strings for clarity.
+;; Doc string says that it applies to all Bookmark+ files, and recommends that you back up your files.
+;;
+(defcustom bookmark-version-control t
+ "Whether to make numbered backups of your bookmarking files.
+This includes bookmark files such as `bookmark-default-file' and also
+Bookmark+ files `bmkp-bmenu-commands-file' and
+`bmkp-bmenu-state-file'.
+
+The option can have value `nospecial', `t', `nil', or `never' . Value
+`nospecial' means to use the `version-control' value. The others have
+the same meanings as for option `version-control'.
+
+Use value `t' if your bookmarks are important to you. Consider also
+using numeric backups. See also nodes `Backup Names' and `Backup
+Deletion' in the Emacs manual."
+ :type '(choice :tag "When to make numbered backups"
+ (const :tag "Use value of option `version-control'" nospecial)
+ (const :tag "Never" never)
+ (const :tag "If existing already" nil)
+ (other :tag "Always" t))
+ :group 'bookmark :group 'bookmark-plus)
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Added value `edit'.
+;;
+(defcustom bookmark-automatically-show-annotations t
+ "*Non-nil means show annotations when jumping to a bookmark.
+If the value is `edit' then open the annotation buffer in edit mode.
+ This has the same effect as using command `bookmark-edit-annotation'.
+Any other non-nil value opens it in read-only mode.
+ This has the same effect as using command `bookmark-show-annotation'."
+ :type '(choice
+ (const :tag "Show annotation read-only" t)
+ (const :tag "Edit annotation" edit)
+ (const :tag "Do not show annotation automatically" nil))
+ :group 'bookmark :group 'bookmark-plus)
+
+
+(when (< emacs-major-version 23)
+
+
+ ;; REPLACES ORIGINAL in `bookmark.el' (Emacs 20-22).
+ ;;
+ ;; Same as Emacs 23+ version of the function.
+ ;; But the behavior is different from vanilla Emacs, because of the different `bookmark-get-bookmark'
+ ;; behavior: Only if BOOKMARK is a name without that property is it looked up in `bookmark-alist'.
+ ;;
+ (defun bookmark-get-bookmark-record (bookmark)
+ "Return the data part of BOOKMARK, that is, all but the name.
+BOOKMARK is a bookmark name or a bookmark record.
+
+If it is a name with text property `bmkp-full-record', or if it is a
+bookmark record, then it is NOT looked up in `bookmark-alist' (it need
+not belong). Only if it is a name without that property is it looked
+up in `bookmark-alist'."
+ (let ((data (cdr (bookmark-get-bookmark bookmark))))
+ ;; A bookmark record is either (NAME ALIST) or (NAME . ALIST).
+ (if (and (null (cdr data)) (consp (caar data)))
+ (car data)
+ data)))
+ )
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; If BOOKMARK is a bookmark-name string that has non-nil property `bmkp-full-record' then just return that.
+;; Only if BOOKMARK is a name without that property is it looked up in `bookmark-alist'.
+;;
+(defun bookmark-get-bookmark (bookmark &optional noerror)
+ "Return the full bookmark (record) that corresponds to BOOKMARK.
+This is just `bmkp-get-bookmark' with non-nil NO-NAME-CHECK-P.
+
+If bookmark is a name with text property `bmkp-full-record', or if it
+is a bookmark record, then it is NOT looked up in `bookmark-alist' (it
+need not belong). Only if it is a name without that property is it
+looked up in `bookmark-alist'. The vanilla Emacs version of this
+function always looks up a string BOOKMARK in `bookmark-alist'.
+
+If you want to ensure that BOOKMARK is in `bookmark-alist' even when
+BOOKMARK is a string, then use `bmkp-get-bookmark-in-alist', not
+`bookmark-get-bookmark' or `bmkp-get-bookmark'."
+ (bmkp-get-bookmark bookmark noerror 'NO-NAME-CHECK-P))
+
+
+;; This is like vanilla `bookmark-get-bookmark' in `bookmark.el', but it has these differences:
+;;
+;; 1. If BOOKMARK is a bookmark-name string that has non-nil property `bmkp-full-record'
+;; then return the value of that property - do not look up the string in `bookmark-alist'.
+;; 2. Handle the should-not-happen case of non-string, non-cons.
+;; 3. Added optional arg NO-NAME-CHECK-P.
+;; 4. Unless NO-NAME-CHECK-P, to be valid when a cons, the car must be a string.
+;;
+(defun bmkp-get-bookmark (bookmark &optional noerror no-name-check-p)
+ "Return the full bookmark (record) that corresponds to BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+
+This function is like vanilla function `bookmark-get-bookmark', except
+for these differences:
+
+1. If BOOKMARK is a bookmark name instead of a full bookmark then
+ return what `bmkp-bookmark-record-from-name' (with no MEMP check)
+ returns. That is, if the name has non-nil text property
+ `bmkp-full-record' then use that, without looking up the string in
+ `bookmark-alist'.
+
+2. By default, to be considered a valid bookmark record, it must have
+ a name. That is, as a cons, its car must be a string.
+
+3. Accepts optional arg NO-NAME-CHECK-P.
+
+Non-nil optional arg NOERROR means return nil if BOOKMARK is not a
+valid bookmark. If NOERROR is nil then raise an error in this case.
+
+Non-nil optional arg NO-NAME-CHECK-P means don't require that the
+bookmark have a name when checking for a valid bookmark. That is,
+don't require that a cons bookmark have a string car. Use this arg if
+you generally want the behavior of `bookmark-get-bookmark' but you
+also want the other advantages of `bmkp-get-bookmark'.
+
+You can use this in place of `bookmark-get-bookmark' and remain
+compatible with vanilla Emacs, if you do either of the following:
+
+* Use non-nil NOERROR.
+* Use nil ERROR and non-nil NO-NAME-CHECK-P.
+
+In those cases you still take advantage of a BOOKMARK that has a name
+with a `bmkp-full-record' property, but there's no requirement that
+BOOKMARK have a name.
+
+This function is like `bmkp-get-bookmark-in-alist', except that
+`bmkp-get-bookmark-in-alist' always tests whether BOOKMARK is in
+`bookmark-alist', regardless of whether BOOKMARK is a string (a
+bookmark name) or a full bookmark. `bmkp-get-bookmark-in-alist' is
+thus a real test for bookmark existence. Use `bmkp-get-bookmark' only
+when you do NOT want to look up the bookmark in `bookmark-alist'."
+ ;; Non-nil NO-NAME-CHECK-P means this, like `bookmark-get-bookmark', checks only for a cons.
+ ;; With nil NO-NAME-CHECK-P, the check is for a cons with a string car. We test for the string (the
+ ;; bookmark name) so that we can distinguish, for example, a list of bookmarks from a single bookmark.
+ (cond ((and (consp bookmark) (or no-name-check-p (stringp (car bookmark)))) ; No test of alist membership.
+ bookmark)
+ ((stringp bookmark) ; No MEMP check.
+ (bmkp-bookmark-record-from-name bookmark noerror))
+ (t (and (not noerror) ; Return nil if NOERROR.
+ (error "Invalid bookmark: `%s'" bookmark)))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Use option `bmkp-new-bookmark-default-names' to obtain the default name.
+;;
+(defun bookmark-make-record ()
+ "Return a new bookmark record (NAME . ALIST) for the current location.
+Start with `bookmark-make-record-function'. If it does not provide a
+bookmark name, then use option `bmkp-new-bookmark-default-names' to
+provide it. If that does not provide it then use
+`bookmark-current-bookmark' or `bookmark-buffer-name', in that order."
+ (let ((record (funcall bookmark-make-record-function))
+ defname)
+ (if (stringp (car record))
+ record
+ (when (car record) (push nil record))
+ (setq defname (catch 'bookmark-make-record
+ (dolist (fn bmkp-new-bookmark-default-names)
+ (when (functionp fn) ; Be sure it is defined and is a function.
+ (let ((val (funcall fn)))
+ (when (and (stringp val) (not (string= "" val)))
+ (throw 'bookmark-make-record val)))))
+ (or bookmark-current-bookmark (bookmark-buffer-name))))
+ (when (and defname (not (stringp defname))) (setq defname (format "%s" defname))) ; Just in case.
+ (when (string= "" defname) (setq defname "<EMPTY NAME>")) ; You never know.
+ (setcar record defname)
+ record)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional args NO-REFRESH-P and NO-MSG-P.
+;; 2. Update the bookmark name also, not just the data, for an existing bookmark.
+;; 3. Use `bmkp-get-bookmark-in-alist' to test whether the bookmark already exists.
+;; 4. Put full bookmark record on bookmark name (inside record) as property `bmkp-full-record'.
+;; 5. Use `bmkp-maybe-save-bookmarks'.
+;; 6. Add the bookmark to `bmkp-modified-bookmarks', and to `bmkp-automatic-bookmarks' if appropriate.
+;; 7. Use `bmkp-refresh/rebuild-menu-list', not `bookmark-bmenu-surreptitiously-rebuild-list'.
+;; 8. Return the bookmark.
+;;
+(defun bookmark-store (bookmark-name data no-overwrite &optional no-refresh-p no-msg-p)
+ "Store the bookmark named BOOKMARK-NAME, giving it DATA.
+Return the new bookmark.
+
+DATA is the bookmark record without its name, i.e., what
+`bmkp-bookmark-data-from-record' returns.
+
+If NO-OVERWRITE is non-nil and bookmark BOOKMARK-NAME already exists
+in the current bookmark list (`bookmark-alist') then record the new
+bookmark but do not discard the old one. The check for existence uses
+`bmkp-get-bookmark-in-alist'.
+
+Non-nil optional arg NO-REFRESH-P means do not refresh/rebuild the
+bookmark-list display.
+
+Non-nil optional arg NO-MSG-P means do not show progress messages.
+
+Note: In spite of the function name, like all functions that define or
+change bookmarks, this function does not necessarily save your
+bookmark file. Saving the file depends on `bookmark-save-flag'."
+ (bookmark-maybe-load-default-file)
+ (let ((bname (copy-sequence bookmark-name))
+ bmk)
+ (unless (featurep 'xemacs)
+ ;; XEmacs's `set-text-properties' does not work on free-standing strings, apparently.
+ (set-text-properties 0 (length bname) () bname))
+ (if (or no-overwrite (not (setq bmk (bmkp-get-bookmark-in-alist bname 'NOERROR))))
+ (push (setq bmk (cons bname data)) bookmark-alist) ; Add new bookmark.
+ (bookmark-set-name bmk bname) ; Overwrite existing bookmark.
+ (setcdr bmk data))
+ ;; Put the full bookmark on its name as property `bmkp-full-record'.
+ ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+ ;; If it needs to be stripped, that will be done when saving.
+ (put-text-property 0 (length bname) 'bmkp-full-record bmk bname)
+ (bmkp-maybe-save-bookmarks)
+ ;; These two are the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+ (unless (memq bmk bmkp-modified-bookmarks)
+ (setq bmkp-modified-bookmarks (cons bmk bmkp-modified-bookmarks)))
+ (when (and (boundp 'bmkp-setting-automatic-bmk-p)
+ (not (memq bmk bmkp-automatic-bookmarks)))
+ (setq bmkp-automatic-bookmarks (cons bmk bmkp-automatic-bookmarks)))
+ (setq bookmark-current-bookmark bname)
+ (unless no-refresh-p (bmkp-refresh/rebuild-menu-list bmk no-msg-p))
+ bmk)) ; Return the bookmark.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Mention `C-c C-M-c', not `C-c C-c'.
+;;
+;;;###autoload (autoload 'bookmark-default-annotation-text "bookmark+")
+(defun bookmark-default-annotation-text (bookmark-name)
+ "Return default annotation text for BOOKMARK-NAME.
+The default annotation text is simply some text explaining how to use
+annotations."
+ (concat "# Type the annotation for bookmark `" bookmark-name "' here.\n"
+ "# All lines that start with a `#' will be deleted.\n"
+ "# Type `C-c C-M-c' when done.\n#\n"
+ "# Author: " (user-full-name) " <" (user-login-name) "@"
+ (system-name) ">\n"
+ "# Date: " (current-time-string) "\n"))
+
+
+;; REPLACES ORIGINAL in `bookmark.el' (Emacs 24.4+).
+;;
+;; Usable for older Emacs versions also.
+;;
+;;;###autoload (autoload 'bookmark-insert-annotation "bookmark+")
+(defun bookmark-insert-annotation (bookmark)
+ "Insert annotation for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+ (setq bookmark (bmkp-bookmark-name-from-record (bmkp-get-bookmark-in-alist bookmark)))
+ (insert (funcall (if (boundp 'bookmark-edit-annotation-text-func)
+ bookmark-edit-annotation-text-func
+ bookmark-read-annotation-text-func)
+ bookmark))
+ (let ((annotation (bookmark-get-annotation bookmark)))
+ (when (and annotation (not (string-equal annotation ""))) (insert annotation))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Derive from value of option `bmkp-annotation-modes-inherit-from'.
+;; 2. First, remove parent map from `bookmark-edit-annotation-mode-map', so it is derived anew.
+;; 3. Corrected typo in doc string: *send-EDITED-*.
+;; 4. Need to use `eval', to pick up option value and reset parent keymap.
+;; 5. Bind `C-x C-q' to `bmkp-show-this-annotation-read-only'.
+;;
+;;;###autoload (autoload 'bookmark-edit-annotation-mode "bookmark+")
+(eval
+ `(progn
+ ;; Get rid of default parent, so `bmkp-annotation-modes-inherit-from' is used for the map.
+ (when (keymapp bookmark-edit-annotation-mode-map)
+ (set-keymap-parent bookmark-edit-annotation-mode-map nil))
+ (define-derived-mode bookmark-edit-annotation-mode ,bmkp-annotation-modes-inherit-from
+ "Edit Bookmark Annotation"
+ "Mode for editing the annotation of a bookmark.
+When you have finished composing, use `C-c C-M-c'.
+
+\\{bookmark-edit-annotation-mode-map}")
+ (define-key bookmark-edit-annotation-mode-map "\C-x\C-q" 'bmkp-show-this-annotation-read-only)
+ ;; Define this key because Org mode co-opts `C-c C-c' as a prefix key.
+ (define-key bookmark-edit-annotation-mode-map "\C-c\C-\M-c" 'bookmark-send-edited-annotation)))
+
+(define-derived-mode bookmark-show-annotation-mode bookmark-edit-annotation-mode
+ "Show Bookmark Annotation"
+ "Mode for displaying the annotation of a bookmark.
+
+\\{bookmark-show-annotation-mode-map}"
+ (setq buffer-read-only t)
+ (define-key bookmark-show-annotation-mode-map "\C-x\C-q" 'bmkp-edit-this-annotation))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Record an empty annotation as nil, not "".
+;; 2. BUG fix: Put point back where it was (on the bookmark just annotated).
+;; 3. Refresh menu list, to pick up the `a' marker.
+;; 4. Make sure it's the annotation buffer that gets killed.
+;; 5. Delete window also, if `misc-cmds.el' loaded.
+;;
+;;;###autoload (autoload 'bookmark-send-edited-annotation "bookmark+")
+(defun bookmark-send-edited-annotation () ; Bound to `C-c C-M-c' in `bookmark-edit-annotation-mode'.
+ "Use buffer contents as annotation for a bookmark.
+Lines beginning with `#' are ignored."
+ (interactive)
+ (unless (derived-mode-p 'bookmark-edit-annotation-mode)
+ (error "Not in mode derived from `bookmark-edit-annotation-mode'"))
+ (goto-char (point-min))
+ (while (< (point) (point-max)) (if (= (following-char) ?#) (bookmark-kill-line t) (forward-line 1)))
+ (let ((annotation (buffer-substring-no-properties (point-min) (point-max)))
+ (bookmark bookmark-annotation-name)
+ (annotation-buf (current-buffer)))
+ (when (string= annotation "") (setq annotation nil))
+ (bookmark-set-annotation bookmark annotation)
+ (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count))
+ (bmkp-refresh/rebuild-menu-list bookmark) ; So display `a' and `*' markers (updated).
+ (if (fboundp 'kill-buffer-and-its-windows)
+ (kill-buffer-and-its-windows annotation-buf) ; Defined in `misc-cmds.el'.
+ (kill-buffer annotation-buf))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Make it a command (added `interactive' spec). Prefix arg means add or edit (choose any bookmark).
+;; 2. Manage buffer-modified-p.
+;; 3. Emacs 26+: Added ignored &rest arg to accommodate vanilla Emacs fix to bug #20150 (not a bug for us).
+;;
+;;;###autoload (autoload 'bookmark-edit-annotation "bookmark+")
+(defun bookmark-edit-annotation (bookmark &rest _IGNORED) ; Bound to `C-x x a e'
+ "Pop up a buffer for editing bookmark BOOKMARK's annotation.
+Interactively, you are prompted for the bookmark name. With a prefix
+arg, you can choose any bookmark. Otherwise, only annotated bookmarks
+are candidates.
+
+Non-interactively, BOOKMARK is a bookmark name or a bookmark record."
+ (interactive
+ (let ((alist (bmkp-annotated-alist-only)))
+ (list (bookmark-completing-read (format "%s annotation for bookmark"
+ (if current-prefix-arg "Add or edit" "Edit"))
+ (bmkp-default-bookmark-name alist)
+ alist
+ nil
+ nil
+ (not current-prefix-arg)))))
+ (pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*"))
+ (bookmark-insert-annotation bookmark)
+ (bookmark-edit-annotation-mode)
+ (setq bookmark-annotation-name bookmark))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Added optional arg ALIST.
+;;
+(defun bookmark-all-names (&optional alist)
+ "Return a list of all bookmark names.
+The names are those of the bookmarks in ALIST or, if nil,
+`bookmark-alist'."
+ (bookmark-maybe-load-default-file)
+ (mapcar (lambda (bmk) (bmkp-bookmark-name-from-record bmk)) (or alist bookmark-alist)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional args ALIST, PRED, and HIST.
+;; 2. Use helper function `bmkp-completing-read-1', which does this:
+;; (a) binds `icicle-delete-candidate-object' to (essentially) `bookmark-delete'.
+;; (b) forces you to enter a non-empty name, if DEFAULT is nil or "".
+;;
+(defun bookmark-completing-read (prompt &optional default alist pred hist use-nil-alist-p)
+ "Read a bookmark name, prompting with PROMPT.
+PROMPT is automatically suffixed with \": \", so do not include that.
+
+DEFAULT is a string or a list of strings. If the user input is empty
+then return the string (or the first string in the list). If DEFAULT
+is nil (absent) then return \"\" for empty input.
+
+The bookmark alist argument used for completion is optional arg ALIST.
+If USE-NIL-ALIST-P is nil, then ALIST defaults to `bookmark-alist'.
+
+Optional arg PRED is a predicate used for completion.
+
+Optional arg HIST is a history variable for completion. Default is
+ `bookmark-history'.
+
+Non-nil optional arg USE-NIL-ALIST-P means do not default ALIST to
+`bookmark-alist': if ALIST is nil then there are no bookmark
+candidates.
+
+If you access this function from a menu, then, depending on the value
+of option `bmkp-menu-popup-max-length' and the number of
+bookmarks in ALIST, you choose the bookmark using a menu or using
+completion.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+ (bmkp-completing-read-1 prompt default alist pred hist nil use-nil-alist-p))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Handles also regions and non-file buffers.
+;; 2. Do not use NO-CONTEXT or POSN if < Emacs 24.
+;;
+(defun bookmark-make-record-default (&optional no-file no-context position visits no-region)
+ "Return the record describing the location of a new bookmark.
+Point must be where the bookmark is to be set.
+
+Non-nil NO-FILE means return only the subset of the record that
+ pertains to the location within the buffer (not also the file name).
+
+Non-nil NO-CONTEXT means do not include the front and rear context
+strings in the record enough.
+
+Non-nil POSITION means record it, not point, as the `position' entry.
+
+Non-nil VISITS means record it as the `visits' entry.
+
+Non-nil NO-REGION means do not include the region end, `end-position'."
+ (unless (> emacs-major-version 23) (setq no-context nil))
+ (let* ((dired-p (and (boundp 'dired-buffers) (car (rassq (current-buffer) dired-buffers))))
+ (buf (buffer-name))
+ (ctime (current-time))
+
+ ;; Begin `let*' dependencies.
+ (regionp (and transient-mark-mode mark-active (> (region-end) (region-beginning))))
+ (beg (if regionp (region-beginning) (or position (point))))
+ (end (if regionp (region-end) (point)))
+ (fcs (and (not no-context) (if regionp
+ (bmkp-position-post-context-region beg end)
+ (bmkp-position-post-context beg))))
+ (rcs (and (not no-context) (if regionp
+ (bmkp-position-pre-context-region beg)
+ (bmkp-position-pre-context beg))))
+ (fcrs (and (not no-context) regionp (bmkp-end-position-pre-context beg end)))
+ (ecrs (and (not no-context) regionp (bmkp-end-position-post-context end))))
+ `(,@(unless no-file
+ `((filename . ,(cond ((buffer-file-name) (bookmark-buffer-file-name))
+ (dired-p nil)
+ (t bmkp-non-file-filename)))))
+ (buffer-name . ,buf)
+ ,@(unless no-context `((front-context-string . ,fcs)))
+ ,@(unless no-context `((rear-context-string . ,rcs)))
+ ,@(unless no-context `((front-context-region-string . ,fcrs)))
+ ,@(unless no-context `((rear-context-region-string . ,ecrs)))
+ (visits . ,(or visits 0))
+ (time . ,ctime)
+ (created . ,ctime)
+ (position . ,beg)
+ ,@(when (and regionp (not no-region)) `((end-position . ,end))))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Unless non-nil arg DO-NOT-PROPERTIZE-P, put full bookmark record on bookmark name (inside record),
+;; as property `bmkp-full-record'.
+;;
+(defun bookmark-alist-from-buffer (&optional do-not-propertize-p)
+ "Read and return a bookmark list (in any format) from the current buffer.
+Unless optional arg DO-NOT-PROPERTIZE-P is non-nil, put the full
+bookmark record on the bookmark name (in the record), as a text
+property. Point is irrelevant and unaffected."
+ (let ((bmks (save-excursion
+ (goto-char (point-min))
+ (if (search-forward bookmark-end-of-version-stamp-marker nil t)
+ (condition-case err
+ (read (current-buffer))
+ (error (error "Cannot read definitions in bookmark file: %s"
+ (error-message-string err))))
+ ;; Else we're dealing with format version 0
+ (if (search-forward "(" nil t)
+ (progn (forward-char -1)
+ (condition-case err
+ (read (current-buffer))
+ (error (error "Cannot read definitions in bookmark file: %s"
+ (error-message-string err)))))
+ ;; Else no hope of getting information here.
+ (error "Buffer is not in bookmark-list format"))))))
+ ;; Put full bookmark on bookmark names as property `bmkp-full-record'.
+ ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+ ;; If property needs to be stripped, that will be done when saving.
+ (unless do-not-propertize-p
+ (let (bname)
+ (dolist (bmk bmks)
+ (setq bname (bmkp-bookmark-name-from-record bmk))
+ (put-text-property 0 (length bname) 'bmkp-full-record bmk bname))))
+ bmks))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Use `bookmark-make-record'.
+;; 2. Use special default prompts for active region, EWW, W3M, and Gnus.
+;; 3. Use function `bmkp-new-bookmark-default-names', in addition to the name that
+;; `bookmark-make-record' comes up with, as the list of default values.
+;; 4. Use `bmkp-completing-read-lax', choosing from current buffer's bookmarks.
+;; 5. Numeric prefix arg (diff from plain): all bookmarks as completion candidates.
+;; 6. Ask for confirmation if (a) not plain `C-u' and (b) NAME names an existing bookmark.
+;; 7. Do not overwrite properties listed in option `bmkp-properties-to-keep'.
+;; 8. Added optional args INTERACTIVEP and NO-REFRESH-P.
+;; 9. Prompt for tags if `bmkp-prompt-for-tags-flag' is non-nil.
+;; 10. Possibly highlight bookmark and other bookmarks in buffer, per `bmkp-auto-light-when-set'.
+;; 11. Make bookmark temporary, if `bmkp-autotemp-bookmark-predicates' says to.
+;; 12. Run `bmkp-after-set-hook'.
+;;
+;;;###autoload (autoload 'bookmark-set "bookmark+")
+(defun bookmark-set (&optional name parg interactivep no-refresh-p) ; `C-x r M', `C-x x c M'
+ "Set a bookmark named NAME, then run `bmkp-after-set-hook'.
+If the region is active (`transient-mark-mode') and nonempty, then
+record the region limits in the bookmark.
+
+If NAME is nil, then prompt for the bookmark name. The default names
+for prompting are as follows (in order of priority):
+
+ * If in W3M mode, then the current W3M title.
+
+ * If in a Gnus mode, then the Gnus summary article header.
+
+ * If on a `man' page, then the page name (command and section).
+
+ * If the region is active and nonempty, then the buffer name followed
+ by \": \" and the region prefix (up to
+ `bmkp-bookmark-name-length-max' chars).
+
+ * The names defined by option `bmkp-new-bookmark-default-names'.
+
+ * The value of variable `bookmark-current-bookmark', the name of the
+ last-used bookmark for the current file.
+
+ * The value returned by function `bookmark-buffer-name'.
+
+For Emacs 23+, all of the names described above are available as
+default values, by repeating `M-n'. For older Emacs versions, the
+first name provided is the only default value.
+
+While entering a bookmark name at the prompt:
+
+ * You can use (lax) completion against bookmarks in the same buffer.
+ If there are no bookmarks in the current buffer, then all bookmarks
+ are completion candidates. (See also below, about a numeric prefix
+ argument.)
+
+ * You can use `C-M-w' to yank words from the buffer to the
+ minibuffer. Repeating `C-M-w' yanks successive words (newlines
+ between yanked words are stripped out).
+
+ * You can use `C-M-u' to insert the name of the last bookmark used in
+ the buffer. This can be useful as an aid to track your progress
+ through a large file. (If no bookmark has yet been used, then
+ `C-M-u' inserts the name of the visited file.)
+
+A prefix argument changes the behavior as follows:
+
+ * Numeric prefix arg: Use all bookmarks as completion candidates,
+ instead of just the bookmarks for the current buffer.
+
+ * Plain prefix arg (`C-u'): Do not overwrite a bookmark that has the
+ same name as NAME, if such a bookmark already exists. Instead,
+ push the new bookmark onto the bookmark alist.
+
+ For use by vanilla Emacs, only the most recently set bookmark named
+ NAME is in effect at any given time, but any others named NAME can
+ become available, should you decide to delete the most recent one.
+
+ For Bookmark+, if option `bmkp-propertize-bookmark-names-flag' is
+ non-`nil' then you can use any number of bookmarks that have the
+ same name. If that option is `nil' then the behavior is the same
+ as for vanilla Emacs.
+
+Bookmark properties listed in option `bmkp-properties-to-keep' are not
+overwritten when you set an existing bookmark. Their existing values
+are kept. Other properties may be updated. Properties such as
+`position' and `visit' are typically updated, for example, to record
+the new position and the number of visits.
+
+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).
+
+From Lisp code:
+
+* Non-nil INTERACTIVEP means the user can be prompted for
+ confirmation, tags, etc., and it is used for the call to
+ `bookmark-store'.
+
+* Non-nil NO-REFRESH-P is also passed to `bookmark-store'. It means
+ do not refresh/rebuild the bookmark-list display."
+ (interactive (list nil current-prefix-arg t))
+ (unwind-protect
+ (progn
+ (bookmark-maybe-load-default-file)
+ (setq bookmark-current-point (point)) ; `bookmark-current-point' is a free var here.
+ ;; Do not set these if they are already set in some other buffer (e.g gnus-art).
+ (unless (and bookmark-yank-point bookmark-current-buffer)
+ (save-excursion (skip-chars-forward " ") (setq bookmark-yank-point (point)))
+ (setq bookmark-current-buffer (current-buffer)))
+ (let* ((record (bookmark-make-record))
+ (defname (cond ((and (eq major-mode 'eww-mode)
+ (fboundp 'bmkp-make-eww-record) ; Emacs 25+
+ (bmkp-eww-title)))
+ ((eq major-mode 'w3m-mode) w3m-current-title)
+ ((eq major-mode 'gnus-summary-mode) (elt (gnus-summary-article-header) 1))
+ ((memq major-mode '(Man-mode woman-mode))
+ (buffer-substring (point-min) (save-excursion (goto-char (point-min))
+ (skip-syntax-forward "^ ")
+ (point))))
+ (t nil)))
+ (defname (and defname (bmkp-replace-regexp-in-string "\n" " " defname)))
+ (bname (or name (bmkp-completing-read-lax
+ "Set bookmark"
+ (bmkp-new-bookmark-default-names defname)
+ (and (or (not parg) (consp parg)) ; No numeric PARG: all bookmarks.
+ (bmkp-specific-buffers-alist-only))
+ nil 'bookmark-history (or (not parg) (consp parg))))))
+ ;; BNAME should not be "" now, since `bmkp-new-bookmark-default-names' should provide default(s)
+ ;; and empty input to `bmkp-completing-read-lax' returns the default. But just in case...
+ (when (and (string= bname "") defname) (setq bname defname))
+ (while (string= "" bname)
+ (message "Enter a NON-EMPTY bookmark name") (sit-for 2)
+ (setq bname (bmkp-completing-read-lax
+ "Set bookmark"
+ (bmkp-new-bookmark-default-names defname)
+ (and (or (not parg) (consp parg)) ; No numeric PARG: all bookmarks.
+ (bmkp-specific-buffers-alist-only))
+ nil 'bookmark-history (or (not parg) (consp parg)))))
+ (let ((old-bmk (bmkp-get-bookmark-in-alist bname 'NOERROR))
+ old-prop)
+ (when (and interactivep bmkp-bookmark-set-confirms-overwrite-p (atom parg) old-bmk
+ (not (y-or-n-p (format "Overwrite bookmark `%s'? " bname))))
+ (error "OK, canceled"))
+ (when old-bmk ; Restore props of existing bookmark per `bmkp-properties-to-keep'.
+ (dolist (prop bmkp-properties-to-keep)
+ (bookmark-prop-set record prop (bookmark-prop-get old-bmk prop)))))
+ ;; Maybe make bookmark temporary.
+ ;; Pass RECORD, not BNAME, so `bookmark-prop-set' DTRT in `bmkp-make-bookmark-temporary'.
+ (if bmkp-autotemp-all-when-set-p
+ (bmkp-make-bookmark-temporary record)
+ (catch 'bookmark-set
+ (dolist (pred bmkp-autotemp-bookmark-predicates)
+ (when (and (functionp pred) (funcall pred bname))
+ (bmkp-make-bookmark-temporary record)
+ (throw 'bookmark-set t)))))
+ (bookmark-store bname (cdr record) (consp parg) no-refresh-p (not interactivep))
+ (when (and interactivep bmkp-prompt-for-tags-flag)
+ (bmkp-add-tags bname (bmkp-read-tags-completing) 'NO-UPDATE-P)) ; Do not update here.
+ (case (and (boundp 'bmkp-auto-light-when-set) bmkp-auto-light-when-set)
+ (autonamed-bookmark (when (bmkp-autonamed-bookmark-p bname)
+ (bmkp-light-bookmark bname)))
+ (non-autonamed-bookmark (unless (bmkp-autonamed-bookmark-p bname)
+ (bmkp-light-bookmark bname)))
+ (any-bookmark (bmkp-light-bookmark bname))
+ (autonamed-in-buffer (bmkp-light-bookmarks (bmkp-autonamed-this-buffer-alist-only)
+ nil interactivep))
+ (non-autonamed-in-buffer (bmkp-light-bookmarks
+ (bmkp-remove-if #'bmkp-autonamed-this-buffer-bookmark-p
+ (bmkp-this-buffer-alist-only))
+ nil interactivep))
+ (all-in-buffer (bmkp-light-this-buffer nil interactivep)))
+ (run-hooks 'bmkp-after-set-hook)
+ (if bookmark-use-annotations
+ (bookmark-edit-annotation bname)
+ (goto-char bookmark-current-point)))) ; `bookmark-current-point' is a free var here.
+ (setq bookmark-yank-point nil
+ bookmark-current-buffer nil)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Put full bookmark record on the name as property `bmkp-full-record'.
+;; 2. Add BOOKMARK to `bmkp-modified-bookmarks'.
+;; 3. The different `bookmark-get-bookmark' behavior from vanilla Emacs means we can get the right bookmark
+;; if it has a name with property `bmkp-full-record', without looking it up in `bookmark-alist'.
+;; But we don't require that BOOKMARK have a name, so calls from vanilla or other code aren't bothered.
+;;
+(defun bookmark-set-name (bookmark newname)
+ "Set name of BOOKMARK to NEWNAME.
+BOOKMARK is a bookmark name or a bookmark record.
+Put the full bookmark on its name as property `bmkp-full-record'.
+Add BOOKMARK to `bmkp-modified-bookmarks'.
+
+If BOOKMARK is a name with text property `bmkp-full-record', or if it
+is a bookmark record, then it is NOT looked up in `bookmark-alist' (it
+need not belong). If it is a name without that property then it is
+looked up in `bookmark-alist'."
+ (setq bookmark (bookmark-get-bookmark bookmark))
+ (setcar bookmark newname)
+ ;; Put the full bookmark on its name as property `bmkp-full-record'.
+ ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+ ;; If it needs to be stripped, that will be done when saving.
+ (put-text-property 0 (length newname) 'bmkp-full-record bookmark newname)
+ ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+ (unless (memq bookmark bmkp-modified-bookmarks)
+ (setq bmkp-modified-bookmarks (cons bookmark bmkp-modified-bookmarks))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Prevent adding a newline in a bookmark name when yanking.
+;;
+;;;###autoload (autoload 'bookmark-yank-word "bookmark+")
+(defun bookmark-yank-word () ; Bound to `C-M-w' in minibuffer when setting bookmark.
+ "Yank the word at point in `bookmark-current-buffer'.
+Repeat to yank consecutive words from the current buffer, appending
+them to the minibuffer. However, newline characters between yanked
+words are stripped out."
+ (interactive)
+ (let ((string (with-current-buffer bookmark-current-buffer
+ (goto-char bookmark-yank-point)
+ (buffer-substring-no-properties (point)
+ (progn (forward-word 1)
+ (setq bookmark-yank-point (point)))))))
+ (setq string (bmkp-replace-regexp-in-string "\n" "" string))
+ (insert string)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Separate renaming of obsolete default bookmark name (do it even if not loading the default file).
+;; 2. Load `bmkp-last-as-first-bookmark-file' if it is non-nil.
+;;
+(defun bookmark-maybe-load-default-file ()
+ "If bookmarks have not yet been loaded, load them.
+If `bmkp-last-as-first-bookmark-file' is non-nil, load it.
+Otherwise, load `bookmark-default-file'."
+ ;; If there is no file at `bookmark-default-file' but there is a file with the obsolete default
+ ;; name, then rename that file to the value of `bookmark-default-file'.
+ ;; Do this regardless of whether it is `bookmark-default-file' that we load here.
+ (when (and (file-exists-p bookmark-old-default-file) (not (file-exists-p bookmark-default-file)))
+ (rename-file bookmark-old-default-file bookmark-default-file))
+ (let ((file-to-load (bmkp-default-bookmark-file)))
+ (and (not bookmarks-already-loaded)
+ (null bookmark-alist)
+ (file-readable-p file-to-load)
+ (bookmark-load file-to-load t 'nosave)
+ (setq bookmarks-already-loaded t))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Save DISPLAY-FUNCTION to `bmkp-jump-display-function' before calling `bookmark-handle-bookmark'.
+;; 2. Update the name and position of an autonamed bookmark, in case it moved.
+;; 3. Possibly highlight bookmark and other bookmarks in buffer, per `bmkp-auto-light-when-jump'.
+;; 4. Added `catch', so a handler can throw to skip the rest of the processing if it wants.
+;;
+(defun bookmark--jump-via (bookmark display-function)
+ "Display BOOKMARK using DISPLAY-FUNCTION.
+Then run `bookmark-after-jump-hook' and show annotations for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+DISPLAY-FUNCTION is as in `bookmark-jump'."
+ (bmkp-record-visit bookmark 'BATCHP)
+ (setq bmkp-jump-display-function display-function)
+ (catch 'bookmark--jump-via
+ (bookmark-handle-bookmark bookmark)
+ (unless (and bmkp-use-w32-browser-p (fboundp 'w32-browser) (bookmark-get-filename bookmark))
+ (let ((win (get-buffer-window (current-buffer) 0)))
+ (when win (set-window-point win (point))))
+ ;; If this is an autonamed bookmark, update its name and position, in case it moved.
+ ;; But don't do this if we're using w32, since we might not have moved to the bookmark position.
+ (when (and (bmkp-autonamed-bookmark-for-buffer-p bookmark (buffer-name))
+ (not bmkp-use-w32-browser-p))
+ (setq bookmark (bmkp-update-autonamed-bookmark bookmark)))
+ (case (and (boundp 'bmkp-auto-light-when-jump) bmkp-auto-light-when-jump)
+ (autonamed-bookmark (when (bmkp-autonamed-bookmark-p bookmark)
+ (bmkp-light-bookmark bookmark nil nil nil 'USE-POINT)))
+ (non-autonamed-bookmark (unless (bmkp-autonamed-bookmark-p bookmark)
+ (bmkp-light-bookmark bookmark nil nil nil 'USE-POINT)))
+ (any-bookmark (bmkp-light-bookmark bookmark nil nil nil 'USE-POINT))
+ (autonamed-in-buffer (bmkp-light-bookmarks
+ (bmkp-remove-if-not #'bmkp-autonamed-bookmark-p
+ (bmkp-this-buffer-alist-only))
+ nil 'MSG))
+ (non-autonamed-in-buffer (bmkp-light-bookmarks (bmkp-remove-if #'bmkp-autonamed-bookmark-p
+ (bmkp-this-buffer-alist-only))
+ nil 'MSG))
+ (all-in-buffer (bmkp-light-this-buffer nil 'MSG))))
+ (let ((orig-buff (current-buffer))) ; Used by `crosshairs-highlight'.
+ (run-hooks 'bookmark-after-jump-hook))
+ (let ((jump-fn (bmkp-get-tag-value bookmark "bmkp-jump")))
+ (when jump-fn (funcall jump-fn)))
+ (when bookmark-automatically-show-annotations (bookmark-show-annotation bookmark))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg REQUIRE-NAME-P. Pass it to `bmkp-get-bookmark'.
+;; 2. Use `bmkp-get-bookmark' instead of `bookmark-get-bookmark', so we can get the right bookmark if
+;; it has a name with property `bmkp-full-record'. But unless REQUIRE-NAME-P, don't require that BOOKMARK
+;; have a name, so calls from vanilla or other code won't be bothered.
+;; 3. Add to beginning, not end, of bookmark record.
+;; 4. Do not use `nconc'.
+;; 5. Respect both old and newer bookmark formats.
+;; 6. Add BOOKMARK to `bmkp-modified-bookmarks'.
+;;
+(defun bookmark-prop-set (bookmark prop val &optional require-name-p)
+ "Set the entry (property) PROP of BOOKMARK to VAL.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a bookmark name then it is looked up in `bookmark-alist'.
+If it is a record then it is NOT looked up (need not belong).
+If it is or has a name that has non-nil property `bmkp-full-record',
+then use the bookmark in `bookmark-alist' that is the value of that
+property. (use `bmkp-get-bookmark', not `bookmark-get-bookmark'.)"
+ (let* ((bmk (bmkp-get-bookmark bookmark nil (not require-name-p)))
+ (cell (assq prop (bmkp-bookmark-data-from-record bmk))))
+ (if cell
+ (setcdr cell val)
+ (setcdr bmk (if (consp (car (cadr bmk)))
+ (list (cons (cons prop val) (cadr bmk))) ; Old format: ("name" ((filename . "f")...))
+ (cons (cons prop val) (cdr bmk))))) ; New format: ("name" (filename . "f")...)
+ ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+ (unless (memq bmk bmkp-modified-bookmarks)
+ (setq bmkp-modified-bookmarks (cons bmk bmkp-modified-bookmarks)))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg FLIP-USE-REGION-P.
+;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
+;; 3. Use `bmkp-jump-1'.
+;; 4. Added note about Icicles `S-delete' to doc string.
+;;
+;;;###autoload (autoload 'bookmark-jump "bookmark+")
+(defun bookmark-jump (bookmark ; Bound to `C-x j j', `C-x r b', `C-x x g'
+ &optional display-function flip-use-region-p)
+ "Jump to bookmark BOOKMARK.
+You may have a problem using this function if the value of variable
+`bookmark-alist' is nil. If that happens, you need to load in some
+bookmarks. See function `bookmark-load' for more about this.
+
+If the file pointed to by BOOKMARK no longer exists, you are asked if
+you wish to give the bookmark a new location. If so, `bookmark-jump'
+jumps to the new location and saves it.
+
+If the bookmark defines a region, then the region is activated if
+`bmkp-use-region' is not-nil or it is nil and you use a prefix
+argument. A prefix arg temporarily flips the value of
+`bmkp-use-region'.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate.
+
+In Lisp code:
+BOOKMARK is a bookmark name or a bookmark record.
+Non-nil DISPLAY-FUNCTION is a function to display the bookmark. By
+ default, use `pop-to-buffer-same-window'.
+Non-nil FLIP-USE-REGION-P flips the value of `bmkp-use-region'."
+ (interactive (list (bookmark-completing-read "Jump to bookmark" (bmkp-default-bookmark-name))
+ nil
+ current-prefix-arg))
+ (bmkp-jump-1 bookmark (or display-function 'bmkp--pop-to-buffer-same-window) flip-use-region-p))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg FLIP-USE-REGION-P.
+;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
+;; 3. Use `bmkp-jump-1'.
+;;
+;;;###autoload (autoload 'bookmark-jump-other-window "bookmark+")
+(defun bookmark-jump-other-window (bookmark &optional flip-use-region-p)
+ ; Bound to `C-x 4 j j', `C-x x j', `C-x x o', `C-x x q'
+ "Jump to bookmark BOOKMARK in another window.
+See `bookmark-jump', in particular for info about using a prefix arg."
+ (interactive (list (bookmark-completing-read "Jump to bookmark (in another window)"
+ (bmkp-default-bookmark-name))
+ current-prefix-arg))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+
+;; REPLACES ORIGINAL in `bookmark.el' (Emacs 27+)
+;;
+;; 1. Added optional arg FLIP-USE-REGION-P.
+;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
+;; 3. Use `bmkp-jump-1'.
+;;
+;;;###autoload (autoload 'bookmark-jump-other-frame "bookmark+")
+(defun bookmark-jump-other-frame (bookmark &optional flip-use-region-p) ; Bound to `C-x 5 B'
+ "Jump to bookmark BOOKMARK in another frame.
+See `bookmark-jump', in particular for info about using a prefix arg."
+ (interactive (list (bookmark-completing-read "Jump to bookmark (in another frame)"
+ (bmkp-default-bookmark-name))
+ current-prefix-arg))
+ (let ((pop-up-frames t)) (bookmark-jump-other-window bookmark flip-use-region-p)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Invoke MS Windows `Open' action if `bmkp-use-w32-browser-p' and if `w32-browser' is defined.
+;; 2. Favor entry `file-handler' over entry `handler'. If the former is available, apply it to the file.
+;; 3. If BOOKMARK has its own handler but that is not a defined function, then use the default handler.
+;; This lets Emacs 22, for instance, handle Emacs 23+ image bookmarks.
+;; 4. Different relocation message for non-file bookmark.
+;;
+(defun bookmark-handle-bookmark (bookmark)
+ "Call BOOKMARK's handler, or `bookmark-default-handler' if it has none.
+Return nil or raise an error.
+
+BOOKMARK is a bookmark name or a bookmark record.
+
+More precisely:
+
+ If `bmkp-use-w32-browser-p' is non-`nil' and `w32-browser' is
+ defined then invoke the MS Windows `Open' action.
+
+ Else, if BOOKMARK has both `file-handler' and `filename' entries
+ then apply the former to the latter.
+
+ Else, if BOOKMARK has a `handler' entry whose value is a defined
+ function then apply it to BOOKMARK.
+
+ Else, apply the default bookmark handler,
+ `bookmark-default-handler', to BOOKMARK.
+
+The default handler changes the current buffer and point.
+
+If the default handler is used and a file error is raised, the error
+is handled as follows:
+ If BOOKMARK has no `filename' entry, do nothing.
+ Else prompt to relocate the file.
+ If relocated, then try again to handle. Else raise a file error."
+ (cond ((and bmkp-use-w32-browser-p (fboundp 'w32-browser) (bookmark-get-filename bookmark))
+ (w32-browser (bookmark-get-filename bookmark))
+ ;; This `throw' is only for the case where this handler is called from `bookmark--jump-via'.
+ ;; It tells `bookmark--jump-via' to skip the rest of what it does after calling the handler.
+ (condition-case nil (throw 'bookmark--jump-via 'BOOKMARK-HANDLE-BOOKMARK) (no-catch nil)))
+ ((functionp (bookmark-prop-get bookmark 'file-handler))
+ (funcall (bookmark-prop-get bookmark 'file-handler) (bookmark-get-filename bookmark)))
+ ((functionp (bookmark-get-handler bookmark))
+ (funcall (bookmark-get-handler bookmark) (bmkp-get-bookmark bookmark)))
+ (t
+ (condition-case err
+ (funcall 'bookmark-default-handler (bmkp-get-bookmark bookmark))
+ (bookmark-error-no-filename ; `file-error'
+ ;; BOOKMARK can be either a bookmark name or a bookmark record.
+ ;; If a record, do nothing - assume it is a bookmark used internally by some other package.
+ (when (stringp bookmark)
+ (let ((file (bookmark-get-filename bookmark))
+ (use-dialog-box nil)
+ (use-file-dialog nil))
+ (when file
+ ;; Ask user whether to relocate the file. If no, signal the file error.
+ (unless (string= file bmkp-non-file-filename) (setq file (expand-file-name file)))
+ (ding)
+ (cond ((y-or-n-p (if (and (string= file bmkp-non-file-filename)
+ (bmkp-get-buffer-name bookmark))
+ "Bookmark's buffer does not exist. Re-create it? "
+ (concat (file-name-nondirectory file) " nonexistent. Relocate \""
+ bookmark "\"? ")))
+ (if (string= file bmkp-non-file-filename)
+ ;; This is probably not the right way to get the correct buffer, but it's
+ ;; better than nothing, and it gives the user a chance to DTRT.
+ (pop-to-buffer (bmkp-get-buffer-name bookmark)) ; Create buffer.
+ (bookmark-relocate bookmark)) ; Relocate to file.
+ (funcall (or (bookmark-get-handler bookmark) 'bookmark-default-handler)
+ (bmkp-get-bookmark bookmark))) ; Try again
+ (t
+ (message "Bookmark not relocated: `%s'" bookmark)
+ (signal (car err) (cdr err)))))))))))
+ (when (stringp bookmark) (setq bookmark-current-bookmark bookmark))
+ ;; $$$$$$ The vanilla code returns nil, but there is no explanation of why and no code seems
+ ;; to use the return value. Perhaps we should return the bookmark instead?
+ nil) ; Return nil if no error.
+
+(put 'bookmark-error-no-filename 'error-conditions
+ '(error bookmark-errors bookmark-error-no-filename))
+(put 'bookmark-error-no-filename 'error-message "Bookmark has no associated file (or directory)")
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Use `bmkp-get-bookmark' instead of `bookmark-get-bookmark', so we can get the right bookmark if
+;; it has a name with property `bmkp-full-record'.
+;; 2. Support regions, buffer names, and entry `file-handler'.
+;; 3. Handle MS Windows `Open' command if `bmkp-use-w32-browser-p' and if `w32-browser' is defined.
+;;
+(defun bookmark-default-handler (bookmark)
+ "Default handler to jump to the location of BOOKMARK.
+Return nil (or raise an error).
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'.
+
+If `bmkp-use-w32-browser-p' is non-nil and function `w32-browser' is
+defined, then call `w32-browser'. That is, use the default MS Windows
+application for the bookmarked file.
+
+If BOOKMARK has entries `file-handler' and `filename', then apply the
+value of the former to the latter.
+
+If BOOKMARK is an old-style Info bookmark, then go to the Info node.
+
+If BOOKMARK records a nonempty region and `bmkp-use-region' is
+ non-nil then activate the region.
+
+Otherwise, call `bmkp-goto-position' to go to the recorded position."
+ (let* ((bmk (bmkp-get-bookmark bookmark))
+ (file (bookmark-get-filename bmk))
+ (buf (bookmark-prop-get bmk 'buffer))
+ (bufname (bmkp-get-buffer-name bmk))
+ (pos (bookmark-get-position bmk))
+ (end-pos (bmkp-get-end-position bmk))
+ (old-info-node (and (not (bookmark-get-handler bookmark)) (bookmark-prop-get bmk 'info-node))))
+
+ (cond ((and bmkp-use-w32-browser-p (fboundp 'w32-browser) file) (w32-browser file))
+ ((and (bookmark-prop-get bookmark 'file-handler) file)
+ (funcall (bookmark-prop-get bookmark 'file-handler) file))
+ (old-info-node ; Emacs 20-21 Info bookmarks - no handler entry.
+ (progn (require 'info)
+ (Info-find-node file old-info-node)
+ (when pos (goto-char pos))))
+ ((not (and bmkp-use-region pos end-pos (/= pos end-pos)))
+ ;; Single-position bookmark (no region). Go to it.
+ (bmkp-goto-position bmk file buf bufname pos
+ (bookmark-get-front-context-string bmk)
+ (bookmark-get-rear-context-string bmk)))
+ (t
+ ;; Bookmark with a region. Go to it and activate the region.
+ (if (and file (file-readable-p file) (not (buffer-live-p buf)))
+;;; $$$$$$$ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
+ (with-current-buffer (find-file-noselect file) (setq buf (buffer-name)))
+ ;; No file found. If no buffer either, then signal that file doesn't exist.
+ (unless (or (and buf (get-buffer buf))
+ (and bufname (get-buffer bufname) (not (string= buf bufname))))
+ (signal 'bookmark-error-no-filename (list 'stringp file))))
+ (set-buffer (or buf bufname))
+ (when bmkp-jump-display-function
+ (save-current-buffer (funcall bmkp-jump-display-function (current-buffer)))
+ (raise-frame))
+ (goto-char (if pos (min pos (point-max)) (point-max)))
+ (when (and pos (> pos (point-max))) (error "Bookmark position is beyond buffer end"))
+ ;; Activate region. Relocate it if it moved. Save relocated bookmark if confirm.
+ (funcall bmkp-handle-region-function bmk)))
+ ;; $$$$$$ The vanilla code returns nil, but there is no explanation of why and no code seems
+ ;; to use the return value. Perhaps we should return the bookmark instead?
+ nil)) ; Return nil if no file error.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg NO-REFRESH-P.
+;; 2. Added bookmark default for interactive use.
+;; 3. Added note about `S-delete' to doc string.
+;; 4. Changed arg name: BOOKMARK -> BOOKMARK-NAME.
+;; 5. Update Dired location too, for Dired bookmark.
+;; 6. Refresh menu list, to show new location.
+;;
+;;;###autoload (autoload 'bookmark-relocate "bookmark+")
+(defun bookmark-relocate (bookmark-name &optional no-refresh-p) ; Not bound
+ "Relocate the bookmark named BOOKMARK-NAME to another file.
+You are prompted for the new file name.
+Non-nil optional arg NO-REFRESH-P means do not refresh/rebuild the
+bookmark-list display.
+
+Changes the file associated with the bookmark.
+Useful when a file has been renamed after a bookmark was set in it.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+ (interactive (list (bookmark-completing-read "Bookmark to relocate" (bmkp-default-bookmark-name))))
+ (bookmark-maybe-historicize-string bookmark-name)
+ (bookmark-maybe-load-default-file)
+ (let* ((icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (bookmark-filename (bookmark-get-filename bookmark-name))
+ (new-filename (abbreviate-file-name
+ (expand-file-name
+ (read-file-name
+ (format "Relocate %s to: " bookmark-name)
+ (file-name-directory bookmark-filename))))))
+ (bookmark-set-filename bookmark-name new-filename)
+ ;; Change location for Dired too, but not if different from original file name (e.g. a cons).
+ (let ((dired-dir (bookmark-prop-get bookmark-name 'dired-directory)))
+ (when (and dired-dir (equal dired-dir bookmark-filename))
+ (bookmark-prop-set bookmark-name 'dired-directory new-filename))))
+ (bmkp-maybe-save-bookmarks)
+ (when (and bookmark-bmenu-toggle-filenames (get-buffer bmkp-bmenu-buffer)
+ (get-buffer-window (get-buffer bmkp-bmenu-buffer) 0)
+ (not no-refresh-p))
+ (with-current-buffer (get-buffer bmkp-bmenu-buffer) ; Do NOT just use `bmkp-refresh/rebuild-menu-list'.
+ (bmkp-refresh-menu-list bookmark-name)))) ; So display new location and `*' marker.
+
+
+;; REPLACES ORIGINAL in `bookmark.el' (it was removed from `bookmark.el' in Emacs 24.3 - Emacs bug #19838).
+;;
+;; No change from original, except provide a better doc string.
+;;
+;;;###autoload (autoload 'bookmark-insert-current-bookmark "bookmark+")
+(unless (fboundp 'bookmark-insert-current-bookmark)
+ (defun bookmark-insert-current-bookmark () ; Emacs 24.3+
+ "Insert current-bookmark name or buffer file name, if none.
+That is, if `bookmark-current-bookmark' in `bookmark-current-buffer'
+is not nil then insert that."
+ (interactive)
+ (let ((str (with-current-buffer bookmark-current-buffer
+ (or bookmark-current-bookmark (bookmark-buffer-name)))))
+ (insert str))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added bookmark default for interactive use.
+;; 2. Do not add any text properties here. That's done in `bmkp-bmenu-propertize-item'.
+;; 3. Added note about `S-delete' to doc string.
+;; 4. Changed arg name: BOOKMARK -> BOOKMARK-NAME.
+;;
+;;;###autoload (autoload 'bookmark-insert-location "bookmark+")
+(defun bookmark-insert-location (bookmark-name &optional no-history) ; `C-x x I' (original: `C-x x f')
+ "Insert file or buffer name for the bookmark named BOOKMARK-NAME.
+If a file is bookmarked, insert the recorded file name.
+If a non-file buffer is bookmarked, insert the recorded buffer name.
+
+Optional arg NO-HISTORY means do not record BOOKMARK-NAME in
+`bookmark-history'.
+
+If you use Icicles then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+ (interactive
+ (let ((bmk (bookmark-completing-read "Insert bookmark location" (bmkp-default-bookmark-name))))
+ (if (> emacs-major-version 21) (list bmk) bmk)))
+ (unless no-history (bookmark-maybe-historicize-string bookmark-name))
+ (insert (bookmark-location bookmark-name))) ; Return the line inserted.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. The different `bookmark-get-bookmark' behavior from vanilla Emacs means we can get the right bookmark
+;; if it has a name with property `bmkp-full-record', without looking it up in `bookmark-alist'.
+;; But we don't require that BOOKMARK have a name, so calls from vanilla or other code aren't bothered.
+;; 2. Pass full bookmark to the various "get" functions.
+;; 3. Location returned can be a buffer name.
+;;
+(defun bookmark-location (bookmark)
+ "Return a description of the location of BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a name with text property `bmkp-full-record', or if it is a
+bookmark record, then it is NOT looked up in `bookmark-alist' (it need
+not belong). If it is a name without that property then it is looked
+up in `bookmark-alist'.
+
+Look first for entry `location', then for entry `buffer-name' or
+`buffer', then for entry `filename'. Return the first such entry
+found, or \"-- Unknown location --\" if none is found."
+ (bookmark-maybe-load-default-file)
+ (setq bookmark (bookmark-get-bookmark bookmark))
+ (or (bookmark-prop-get bookmark 'location)
+ (bmkp-get-buffer-name bookmark) ; Entry `buffer-name'.
+ (bookmark-prop-get bookmark 'buffer) ; Entry `buffer'.
+ (bookmark-get-filename bookmark)
+ "-- Unknown location --"))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added BATCHP arg. Return OLD if BATCHP is non-nil and NEW is nil.
+;; 2. Use `bmkp-completing-read-lax', not `read-from-minibuffer', for new name.
+;; 3. Put `bmkp-full-record' property on new name.
+;; 4. Rename also in marked and omitted lists.
+;; 5. Added note about `S-delete' to doc string.
+;; 6. Refresh menu list, to show new name.
+;;
+;;;###autoload (autoload 'bookmark-rename "bookmark+")
+(defun bookmark-rename (old &optional new batchp) ; Not bound in Bookmark+
+ "Change bookmark's name from OLD to NEW.
+Interactively:
+ If called from the keyboard, then prompt for OLD.
+ If called from the menubar, select OLD from a menu.
+If NEW is nil, then prompt for its string value (unless BATCH).
+
+When entering the NEW name you can use completion against existing
+bookmark names. This completion is lax, so you can easily edit an
+existing name. See `bookmark-set' for particular keys available
+during this input.
+
+If BATCHP is non-nil, then do not rebuild the bookmark list. (NEW
+should be non-nil if BATCH is non-nil.)
+
+If you use Icicles then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+ (interactive (list (bookmark-completing-read "Old bookmark name" (bmkp-default-bookmark-name))))
+ (bookmark-maybe-historicize-string old)
+ (bookmark-maybe-load-default-file)
+ (setq bookmark-current-point (point)) ; `bookmark-current-point' is a free var here.
+ (save-excursion (skip-chars-forward " ") (setq bookmark-yank-point (point)))
+ (setq bookmark-current-buffer (current-buffer))
+ (let ((newname (or new (and (not batchp) (bmkp-completing-read-lax "New name" old)))))
+;;; $$$$$$ (read-from-minibuffer "New name: " nil
+;;; (let ((now-map (copy-keymap minibuffer-local-map)))
+;;; (define-key now-map "\C-w" 'bookmark-yank-word)
+;;; now-map)
+;;; nil 'bookmark-history))))
+ (when newname
+ (bookmark-set-name old newname) ; (This also puts `bmkp-full-record' on bookmark name.)
+ (bmkp-rename-for-marked-and-omitted-lists old newname) ; Rename in marked & omitted lists, if present.
+ (setq bookmark-current-bookmark newname)
+ (unless batchp
+ (if (and (get-buffer bmkp-bmenu-buffer) (get-buffer-window (get-buffer bmkp-bmenu-buffer) 0))
+ (with-current-buffer (get-buffer bmkp-bmenu-buffer)
+ (bmkp-refresh-menu-list newname)) ; So the new name is displayed.
+ (bookmark-bmenu-surreptitiously-rebuild-list)))
+ (bmkp-maybe-save-bookmarks))
+ (or newname old))) ; NEWNAME is nil only if BATCHP is non-nil and NEW was nil.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added bookmark default for interactive use.
+;; 2. Added note about `S-delete' to doc string.
+;; 3. Changed arg name: BOOKMARK -> BOOKMARK-NAME.
+;;
+(or (fboundp 'bmkp-ORIG-bookmark-insert)
+(fset 'bmkp-ORIG-bookmark-insert (symbol-function 'bookmark-insert)))
+
+;;;###autoload (autoload 'bookmark-insert "bookmark+")
+(defun bookmark-insert (bookmark-name) ; Bound to `C-x x i'
+ "Insert the text of a bookmarked file.
+BOOKMARK-NAME is the name of the bookmark.
+You may have a problem using this function if the value of variable
+`bookmark-alist' is nil. If that happens, you need to load in some
+bookmarks. See function `bookmark-load' for more about this.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate."
+ (interactive (list (bookmark-completing-read "Insert bookmark contents" (bmkp-default-bookmark-name))))
+ (bmkp-ORIG-bookmark-insert bookmark-name))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Accept a bookmark or a bookmark name as arg.
+;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
+;; 3. Use `bmkp-get-bookmark' instead of `bookmark-get-bookmark', so we can get the right bookmark if
+;; it has a name with property `bmkp-full-record'.
+;; 4. Use `bmkp-get-bookmark-in-alist', not `bookmark-get-bookmark', when checking `bookmark-current-bookmark'.
+;; 5. Remove highlighting for the bookmark.
+;; 6. Doc string includes note about `S-delete' for Icicles.
+;; 7. Update `bmkp-latest-bookmark-alist', `bmkp-bmenu-omitted-bookmarks', and `bmkp-automatic-bookmarks'.
+;; 8. Increment `bookmark-alist-modification-count' even when BATCHP is non-nil.
+;;
+;;;###autoload (autoload 'bookmark-delete "bookmark+")
+(defun bookmark-delete (bookmark &optional batchp) ; Bound to `C-x x d'
+ "Delete the BOOKMARK from the bookmark list.
+BOOKMARK is a bookmark name or a bookmark record.
+Interactively, default to the \"current\" bookmark (that is, the one
+most recently used in this file), if it exists.
+
+If BOOKMARK is a name and it has property `bmkp-full-record' then use
+that property along with the name to find the bookmark to delete. If
+it is or has a name without property `bmkp-full-record' then
+delete (only) the first bookmark in `bookmark-alist' with that name.
+
+Optional arg BATCHP means do not update buffer `*Bookmark List*'.
+
+If you use Icicles, then you can use `S-delete' during completion of a
+bookmark name to delete the bookmark named by the current completion
+candidate. In this way, you can delete multiple bookmarks."
+ (interactive (list (bookmark-completing-read "Delete bookmark" (bmkp-default-bookmark-name))))
+
+ ;; $$$$$$ Instead of loading unconditionally, maybe we should just try to delete conditionally?
+ ;; IOW, why not (when bookmarks-already-loaded BODY) instead of `bookmark-maybe-load-default-file'?
+ ;; If it gets called on a hook that gets run before ever loading, then should probably do nothing.
+ ;; Leaving it as is for now (2011-04-06).
+ (bookmark-maybe-load-default-file)
+ (let* ((bmk (bmkp-get-bookmark bookmark 'NOERROR))
+ (bname (bmkp-bookmark-name-from-record bmk))) ; BOOKMARK might have been a bookmark.
+ (when bname ; Do nothing if BOOKMARK does not represent a bookmark.
+ (bookmark-maybe-historicize-string bname)
+ (when (fboundp 'bmkp-unlight-bookmark) (bmkp-unlight-bookmark bmk 'NOERROR))
+ (setq bookmark-alist (delq bmk bookmark-alist)
+ bmkp-latest-bookmark-alist (delq bmk bmkp-latest-bookmark-alist)
+ bmkp-automatic-bookmarks (delq bmk bmkp-automatic-bookmarks)
+ bmkp-bmenu-omitted-bookmarks (bmkp-delete-bookmark-name-from-list
+ bname bmkp-bmenu-omitted-bookmarks))
+ (unless (bmkp-get-bookmark-in-alist bookmark-current-bookmark 'NOERROR)
+ (setq bookmark-current-bookmark nil)) ; Make this nil if last occurrence of BMK was deleted.
+ ;; Do NOT refresh/rebuild if BATCHP. Caller must do that if batching deletions.
+ (unless batchp (bmkp-refresh/rebuild-menu-list))
+ (bmkp-maybe-save-bookmarks)))) ; Increments `bookmark-alist-modification-count'.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Use `bmkp-current-bookmark-file', not `bookmark-default-file'.
+;; 2. Update `bmkp-last-as-first-bookmark-file' if it is non-nil.
+;; 3. Reset `bmkp-modified-bookmarks' to ().
+;; 4. Call `bmkp-refresh/rebuild-menu-list'.
+;;
+;;;###autoload (autoload 'bookmark-save "bookmark+")
+(defun bookmark-save (&optional parg file) ; Bound to `C-x x s'
+ "Save currently defined bookmarks.
+Save by default in the file named by variable
+`bmkp-current-bookmark-file'. With a prefix arg, you are prompted for
+the file to save to.
+
+If `bmkp-last-as-first-bookmark-file' is non-nil, update its value to
+the file being saved.
+
+To load bookmarks from a specific file, use `\\[bookmark-load]'
+\(`bookmark-load').
+
+If called from Lisp:
+ With nil PARG and nil FILE, use file `bmkp-current-bookmark-file'.
+ With non-nil FILE, use file FILE.
+ With non-nil PARG, prompt the user for the file to use."
+ (interactive "P")
+ (bookmark-maybe-load-default-file)
+ (let ((file-to-save
+ (cond (file) ; Use FILE provided.
+ (parg (bmkp-read-bookmark-file-name
+ "File to save bookmarks in: " nil
+ (bmkp-read-bookmark-file-default)))
+ ((not parg) bmkp-current-bookmark-file))))
+ (when (file-directory-p file-to-save) (error "`%s' is a directory, not a file" file-to-save))
+ (when (and bmkp-last-as-first-bookmark-file
+ bookmark-save-flag) ; nil if temporary bookmarking mode.
+ (customize-save-variable 'bmkp-last-as-first-bookmark-file file-to-save))
+ (bookmark-write-file file-to-save))
+ ;; Indicate by the count that we have synced the current bookmark file.
+ ;; If an error has already occurred somewhere, the count will not be set, which is what we want.
+ (setq bookmark-alist-modification-count 0
+ bmkp-modified-bookmarks ())
+ (bmkp-refresh/rebuild-menu-list)) ; $$$$$$ Should this be done only when interactive?
+
+
+;; From `mule-util.el'
+;;
+(eval-when-compile
+ (defmacro with-coding-priority (coding-systems &rest body)
+ "Execute BODY like `progn' with CODING-SYSTEMS at the front of priority list.
+CODING-SYSTEMS is a list of coding systems. See `set-coding-system-priority'.
+This affects the implicit sorting of lists of coding systems returned by
+operations such as `find-coding-systems-region'."
+ (let ((current (make-symbol "current")))
+ `(let ((,current (coding-system-priority-list)))
+ (apply #'set-coding-system-priority ,coding-systems)
+ (unwind-protect
+ (progn ,@body)
+ (apply #'set-coding-system-priority ,current))))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Use `write-file', not `write-region', so backup files are made.
+;; 2. Do not save temporary bookmarks (`bmkp-temporary-bookmark-p').
+;; 3. Added optional arguments ADD and ALT-MSG.
+;; Do not delete region if ADD. Position point depending on ADD.
+;; 4. Delete contents only if file does not exist (just in case). Else `bookmark-maybe-upgrade-file-format'.
+;; 5. Insert code piecewise, to improve performance when saving `bookmark-alist'.
+;; (Do not let `pp' parse all of `bookmark-alist' at once.)
+;; 6. Unless `bmkp-propertize-bookmark-names-flag', remove text properties from bookmark name and file name.
+;; Remove them also from bookmark names in a sequence bookmark `sequence' entry.
+;; 7. Bind `print-circle' and `print-gensym' around `pp', to record bNAME with `bmkp-full-record' prop, when
+;; appropriate.
+;; 8. Use `case', not `cond'.
+;; 9. Run `bmkp-write-bookmark-file-hook' functions after writing the bookmark file.
+;;
+(defun bookmark-write-file (file &optional add alt-msg)
+ "Write `bookmark-alist' to FILE.
+Bookmarks that have a non-nil `bmkp-temp' entry are not saved.
+They are removed from the bookmark file, but not from the current
+bookmark list.
+
+Non-nil optional arg ADD means do not replace the bookmarks in FILE.
+If the value is `append' then append `bookmark-list' to them. Any
+other non-nil value means prepend `bookmark-list' to them. Prepending
+means that for some operations the copied bookmarks take precedence
+over existing ones with the same name (since an alist is used).
+
+Non-nil ALT-MSG is a message format string to use in place of the
+default, \"Saving bookmarks to file `%s'...\". The string must
+contain a `%s' construct, so that it can be passed along with FILE to
+`format'. At the end, \"done\" is appended to the message."
+ (let ((msg (or alt-msg "Saving bookmarks to file `%s'..."))
+ (coding-system-for-write (if (boundp 'bookmark-file-coding-system) ; Emacs 25.2+.
+ (or coding-system-for-write bookmark-file-coding-system 'utf-8-emacs)
+ coding-system-for-write))
+ (print-length nil)
+ (print-level nil)
+ (rem-all-p (or (not (> emacs-major-version 20)) ; Cannot: (not (boundp 'print-circle)).
+ (not bmkp-propertize-bookmark-names-flag)))
+ (existing-buf (get-file-buffer file))
+ (emacs-lisp-mode-hook nil) ; Avoid inserting automatic file header if existing empty file, so
+ (lisp-mode-hook nil) ; better chance `bookmark-maybe-upgrade-file-format' signals error.
+ bname fname last-fname start end)
+ (when (file-directory-p file) (error "`%s' is a directory, not a file" file))
+ (message msg (abbreviate-file-name file))
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
+ (goto-char (point-min))
+ (if (file-exists-p file)
+ (bookmark-maybe-upgrade-file-format)
+ (delete-region (point-min) (point-max)) ; In case a find-file hook inserted a header, etc.
+ (unless (boundp 'bookmark-file-coding-system) ; Emacs < 25.2.
+ (bookmark-insert-file-format-version-stamp))
+ (insert "(\n)"))
+ (setq start (and (file-exists-p file)
+ (or (save-excursion (goto-char (point-min))
+ (search-forward (concat bookmark-end-of-version-stamp-marker "(")
+ nil t))
+ (error "Invalid bookmark-file")))
+ end (and start
+ (or (save-excursion (goto-char start) (and (looking-at ")") start)) ; Bmk list = ().
+ (save-excursion (goto-char (point-max)) (re-search-backward "^)" nil t))
+ (error "Invalid bookmark-file"))))
+ (if (not start) ; New file, no header yet.
+ (goto-char 2)
+ ;; Existing file - delete old bookmarks unless ADD.
+ (unless add (delete-region start end))
+ (goto-char (if (eq add 'append) end start)))
+ (dolist (bmk bookmark-alist)
+ (unless (bmkp-temporary-bookmark-p bmk)
+ (setq bname (bookmark-name-from-full-record bmk)
+ fname (bookmark-get-filename bmk))
+ (cond (rem-all-p ; Remove text properties from bookmark name and file name.
+ (set-text-properties 0 (length bname) () bname)
+ (when fname (set-text-properties 0 (length fname) () fname)))
+ (t ; Remove property `face' and any Icicles internal properties.
+ (remove-text-properties 0 (length bname) '(face nil
+ display nil
+ help-echo nil
+ rear-nonsticky nil
+ icicle-fancy-candidates nil
+ icicle-mode-line-help nil
+ icicle-special-candidate nil
+ icicle-user-plain-dot nil
+ icicle-whole-candidate nil
+ invisible nil)
+ bname)
+ (when (boundp 'icicle-candidate-properties-alist) ; Multi-completion indexes + text props.
+ (dolist (entry icicle-candidate-properties-alist)
+ (put-text-property 0 (length bname) (car (cadr entry)) nil bname)))))
+ (setcar bmk bname)
+ (when (setq last-fname (assq 'filename bmk)) (setcdr last-fname fname))
+ (let ((print-circle bmkp-propertize-bookmark-names-flag)
+ (print-gensym bmkp-propertize-bookmark-names-flag))
+ (if (not (and rem-all-p (bmkp-sequence-bookmark-p bmk)))
+ (pp bmk (current-buffer))
+ ;; Remove text properties from bookmark names in the `sequence' entry of sequence bookmark.
+ (insert "(\"" (let ((seqbname (copy-sequence (bookmark-name-from-full-record bmk))))
+ (set-text-properties 0 (length seqbname) () seqbname)
+ seqbname)
+ "\"\n")
+ (dolist (prop (cdr bmk))
+ (if (not (eq 'sequence (car prop)))
+ (insert " " (pp-to-string prop))
+ (insert " (sequence " (mapconcat (lambda (bname)
+ (let ((name (copy-sequence bname)))
+ (set-text-properties 0 (length name) () name)
+ (concat "\"" name "\"")))
+ (cdr prop) " ")
+ ")\n")))
+ (insert " )\n")))))
+ (when (boundp 'bookmark-file-coding-system) ; Emacs 25.2+. See bug #25365
+ ;; Make sure specified encoding can encode the bookmarks. If not, suggest utf-8-emacs as default.
+ (with-coding-priority '(utf-8-emacs)
+ (setq coding-system-for-write (select-safe-coding-system (point-min) (point-max)
+ (list t coding-system-for-write))))
+ (when start (delete-region 1 (1- start))) ; Delete old header.
+ (goto-char 1)
+ (bookmark-insert-file-format-version-stamp coding-system-for-write))
+ (let ((version-control (case bookmark-version-control
+ ((nil) nil)
+ (never 'never)
+ (nospecial version-control)
+ (t t)))
+ (require-final-newline t)
+ (errorp nil))
+ (condition-case nil
+ (write-file file)
+ (file-error (setq errorp t)
+ ;; Do NOT raise error. (Need to be able to exit.)
+ (let ((msg (format "CANNOT WRITE FILE `%s'" file)))
+ (if (fboundp 'display-warning)
+ (display-warning 'bookmark-plus msg)
+ (message msg)
+ (sit-for 4)))))
+ (when (boundp 'bookmark-file-coding-system) ; Emacs 25.2+
+ (setq bookmark-file-coding-system coding-system-for-write))
+ (unless existing-buf (kill-buffer (current-buffer)))
+ (run-hook-with-args 'bmkp-write-bookmark-file-hook file)
+ (unless errorp (message (concat msg "done") file))))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg DUPLICATES-OK.
+;;
+;; 2. Unless DUPLICATES-OK is non-nil, if a bookmark in NEW-LIST is `equal' to a bookmark in `bookmark-alist'
+;; then do not rename it and do not add it - just ignore it.
+;;
+;; 3. Return value includes how many bookmarks were added and renamed.
+;; If RETURN-BMKS is non-nil then it also includes which bookmarks were added.
+;;
+(defun bookmark-import-new-list (new-list &optional duplicates-ok return-bmks)
+ "Add NEW-LIST of bookmarks to `bookmark-alist'.
+Unless optional arg DUPLICATES-OK is non-nil, ignore bookmarks that
+are `equal' to bookmarks in `bookmark-alist'. (This means that all of
+their information is `equal', not just their names. This includes
+their tags and annotations.)
+
+Rename new bookmarks that are not ignored, as needed, using suffix
+\"<N>\" (N=2,3...) when they conflict with existing bookmark names.
+
+Return a list (NB-RENAMED NB-ADDED BMKS-ADDED) of the number renamed,
+the number added, and the full bookmarks that were added. If
+RETURN-BMKS is nil then BMKS-ADDED is just nil (the bookmarks are not
+returned)."
+ (let ((names (bookmark-all-names))
+ (nb-added 0)
+ (nb-renamed 0)
+ (bmks-added ()))
+ (dolist (full-bmk new-list)
+ (when (or (and (not (member full-bmk bookmark-alist)) ; Check even if DUPLICATES-OK, to update ADDEDP.
+ (setq nb-added (1+ nb-added)))
+ duplicates-ok)
+ (when (bookmark-maybe-rename full-bmk names) (setq nb-renamed (1+ nb-renamed)))
+ (setq bookmark-alist (nconc bookmark-alist (list full-bmk)))
+ (push (bookmark-name-from-full-record full-bmk) names)
+ (when return-bmks (push full-bmk bmks-added))))
+ (list nb-renamed nb-added bmks-added)))
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Return non-nil iff bookmark was renamed.
+;;
+(defun bookmark-maybe-rename (full-record names)
+ "Rename bookmark FULL-RECORD if its current name is already used.
+This is a helper for `bookmark-import-new-list'.
+Return non-nil if the bookmark was renamed, nil otherwise."
+ (let ((found-name (bookmark-name-from-full-record full-record)))
+ (when (member found-name names)
+ (let ((count 2)
+ (new-name found-name))
+ (while (member new-name names)
+ (setq new-name (concat found-name (format "<%d>" count))
+ count (1+ count)))
+ (bookmark-set-name full-record new-name)
+ (not (string= found-name new-name))))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Prefix arg means OVERWRITE.
+;; 2. Return the list of bookmarks read from FILE.
+;; 3. Use `bmkp-read-bookmark-file-name', not `read-file-name', and use different default.
+;; 4. If OVERWRITE is non-nil:
+;; * Update `bmkp-last-bookmark-file' to `bmkp-current-bookmark-file'.
+;; * Update `bmkp-current-bookmark-file' to FILE.
+;; * Reset bmenu stuff: `bmkp-bmenu-marked-bookmarks', `bmkp-modified-bookmarks',
+;; `bmkp-flagged-bookmarks', `bmkp-bmenu-omitted-bookmarks', `bmkp-bmenu-filter-function'.
+;; * If `bmkp-last-as-first-bookmark-file', then update it to FILE and save it to disk.
+;; 5. If the bookmark-file buffer already existed, do not kill it after loading.
+;; 6. Set `bookmarks-already-loaded' regardless of FILE (not just `bookmark-default-file').
+;; 7. Update `bmkp-sorted-alist' (it's a cache).
+;; 8. Final msg says whether overwritten.
+;; 9. Run `bmkp-read-bookmark-file-hook' after reading the bookmark file.
+;; 10. Call `bmkp-bmenu-refresh-menu-list' at end, if interactive.
+;;
+;;;###autoload (autoload 'bookmark-load "bookmark+")
+(defun bookmark-load (file &optional overwrite batchp) ; Bound to `C-x x l'
+ "Load bookmarks from FILE (which must be in the standard format).
+Return the list of bookmarks read from FILE.
+Without a prefix argument (argument OVERWRITE is nil), add the newly
+loaded bookmarks to those already current. They are saved to the
+current bookmark file when bookmarks are saved.
+
+If you do not use a prefix argument, then no existing bookmarks are
+overwritten. If you load some bookmarks that have the same names as
+bookmarks already defined in your Emacs session, numeric suffixes
+\"<2>\", \"<3>\",... are appended as needed to the names of those new
+bookmarks to distinguish them.
+
+With a prefix argument, switch the bookmark file currently used,
+*replacing* all currently existing bookmarks with the newly loaded
+bookmarks. In this case, the value of `bmkp-current-bookmark-file'is
+backed up to `bmkp-last-bookmark-file' and then changed to FILE, so
+bookmarks will subsequently be saved to FILE.
+
+If `bmkp-last-as-first-bookmark-file' is non-nil and is not FILE then
+it is changed to FILE and saved persistently, so that the next Emacs
+session will start with it as the bookmark file. (The value of
+`bookmark-default-file' is unaffected.)
+
+Interactively, if any bookmarks have been modified since last saved
+then you are asked whether you want to first save them before loading
+FILE. If you hit `C-g' then both saving and loading are canceled.
+
+`bookmark-load' runs `bmkp-read-bookmark-file-hook' after reading the
+bookmark file.
+
+When called from Lisp, non-nil optional arg BATCHP means this is not
+an interactive call. In this case, do not interact with the user: do
+not ask whether to save the current (unsaved) bookmark list before
+loading; do not display any load progress messages; and do not
+update/refresh buffer `*Bookmark List*'.
+
+If BATCHP is `save' and bookmarks have been modified since the
+bookmark list was last saved, then save the bookmark list before
+loading.
+
+If BATCHP is any other non-nil value besides `save', do not save the
+bookmark list.
+
+Your initial bookmark file, either `bmkp-last-as-first-bookmark-file'
+or `bookmark-default-file', is loaded automatically by Emacs the first
+time you use bookmarks in a session - you do not need to load it
+manually. Use `bookmark-load' only to load extra bookmarks (with no
+prefix arg) or an alternative set of bookmarks (with a prefix arg).
+
+If you use `bookmark-load' to load a file that does not contain a
+proper bookmark alist, then when bookmarks are saved the current
+bookmark file will likely become corrupted. You should load only
+bookmark files that were created using the bookmark functions."
+ (interactive
+ (list (let ((default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (bmkp-default-bookmark-file)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name
+ (if current-prefix-arg "Switch to bookmark file: " "Add bookmarks from file: ")
+ (or (file-name-directory default) "~/")
+ default
+ t))
+ current-prefix-arg))
+ ;; Maybe save first.
+ (when (or (eq batchp 'save)
+ (and (not batchp) (> bookmark-alist-modification-count 0)
+ (condition-case err
+ (yes-or-no-p "Save current bookmarks before loading? (`C-g': cancel load) ")
+ (quit (error "OK, canceled"))
+ (error (error (error-message-string err))))))
+ (bookmark-save))
+ ;; Load.
+ (setq file (abbreviate-file-name (expand-file-name file)))
+ (when (file-directory-p file) (error "`%s' is a directory, not a file" file))
+ (unless (file-readable-p file) (error "Cannot read bookmark file `%s'" file))
+ (unless batchp (message "Loading bookmarks from `%s'..." file))
+ (let ((existing-buf (get-file-buffer file))
+ blist)
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
+ (goto-char (point-min))
+ (bookmark-maybe-upgrade-file-format)
+ (setq blist (bookmark-alist-from-buffer))
+ (unless (listp blist) (error "Invalid bookmark list in `%s'" file))
+ (cond (overwrite
+ (setq bmkp-last-bookmark-file bmkp-current-bookmark-file
+ bmkp-current-bookmark-file file
+ bookmark-alist blist
+ bookmark-alist-modification-count 0)
+ (setq bmkp-bmenu-marked-bookmarks () ; Start from scratch.
+ bmkp-modified-bookmarks ()
+ bmkp-flagged-bookmarks ()
+ bmkp-bmenu-omitted-bookmarks (condition-case nil
+ (eval (car (get 'bmkp-bmenu-omitted-bookmarks
+ 'saved-value)))
+ (error nil))
+ bmkp-bmenu-filter-function nil)
+ (when (and bmkp-last-as-first-bookmark-file
+ (not (bmkp-same-file-p bmkp-last-as-first-bookmark-file file)))
+ (customize-save-variable 'bmkp-last-as-first-bookmark-file file)))
+ (t
+ (bookmark-import-new-list blist)
+ (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count))))
+ (setq bookmarks-already-loaded t ; Systematically, whenever any file is loaded.
+ bmkp-sorted-alist (bmkp-sort-omit bookmark-alist))
+ (when (boundp 'bookmark-file-coding-system) ; Emacs 25.2+
+ (setq bookmark-file-coding-system buffer-file-coding-system))
+ (run-hook-with-args 'bmkp-read-bookmark-file-hook blist file)
+ (unless (eq existing-buf (current-buffer)) (kill-buffer (current-buffer))))
+ (unless batchp ; If appropriate, *CALLER* MUST refresh/rebuild, if BATCHP.
+ (bmkp-refresh/rebuild-menu-list)
+ (message "%s bookmarks in `%s'" (if overwrite "Switched to" "Added") file))
+ blist)) ; Return the list of bookmarks read from FILE.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Make it a command (added `interactive' spec).
+;; 2. Use `bmkp-get-bookmark' instead of `bookmark-get-bookmark', so we can get the right bookmark if
+;; it has a name with property `bmkp-full-record'.
+;; 3. Handle external annotations (jump to their destinations).
+;; 4. Added optional arg MSG-P. Show message if no annotation.
+;; 5. If `bookmark-automatically-show-annotations' is `edit' then this is `bookmark-edit-annotation'.
+;; 6. Name buffer after the bookmark.
+;; 7. Highlight the title, using face `bmkp-heading'.
+;; 8. MSG-P means message if no annotation.
+;; 9. Set `bookmark-annotation-name'.
+;; 10. Manage `buffer-modified-p'.
+;; 11. Use `, not ', in title. (Both are tolerated.)
+;; 12. Fit frame to buffer if `one-windowp'.
+;; 13. Restore frame selection.
+;;
+;;;###autoload (autoload 'bookmark-show-annotation "bookmark+")
+(defun bookmark-show-annotation (bookmark &optional msg-p) ; Bound to `C-x x a s'
+ "Show the annotation for BOOKMARK, or follow it if external.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a bookmark name then it is looked up in `bookmark-alist'.
+If it is a record then it is NOT looked up (need not belong).
+If it is or has a name that has non-nil property `bmkp-full-record',
+then use the bookmark in `bookmark-alist' that is the value of that
+property. Raise no error if it has no name.
+
+If the annotation is external then jump to its destination.
+If no annotation and MSG-P is non-nil, show a no-annotation message.
+
+Opens in read-only or edit mode, as chosen by option
+`bookmark-automatically-show-annotations'. You can toggle between
+read-only and edit mode using `C-x C-q'."
+ (interactive (list (bookmark-completing-read "Show annotation of bookmark"
+ (bmkp-default-bookmark-name)
+ (bmkp-annotated-alist-only)
+ nil
+ nil
+ 'USE-NIL-ALIST-P)))
+ (let* ((bmk (bmkp-get-bookmark bookmark 'NOERROR))
+ (bname (bmkp-bookmark-name-from-record bmk))
+ (ann (and bmk (bookmark-get-annotation bmk)))
+ (external (and ann (bmkp-get-external-annotation ann))))
+ (if external
+ (bmkp-visit-external-annotation external msg-p)
+ (if (not (and ann (not (string-equal ann ""))))
+ (when msg-p (message "Bookmark has no annotation"))
+ (if (eq 'edit bookmark-automatically-show-annotations)
+ (bookmark-edit-annotation bookmark)
+ (let ((oframe (selected-frame)))
+ (save-selected-window
+ (pop-to-buffer (get-buffer-create (format "*`%s' Annotation*" bname)))
+ (let ((buffer-read-only nil) ; Because buffer might already exist, in view mode.
+ (buf-modified-p (buffer-modified-p)))
+ (delete-region (point-min) (point-max))
+ (insert (concat "Annotation for bookmark `" bname "':\n\n"))
+ ;; Use `font-lock-ignore' property from library `font-lock+.el', because Org mode
+ ;; uses font-lock, which would otherwise wipe out the highlighting added here.
+ (add-text-properties (line-beginning-position -1) (line-end-position 1)
+ '(face bmkp-heading
+ font-lock-ignore t))
+ (insert ann)
+ (set-buffer-modified-p buf-modified-p))
+ (goto-char (point-min))
+ (bookmark-show-annotation-mode)
+ (when (fboundp 'fit-frame-if-one-window) (fit-frame-if-one-window))
+ (setq bookmark-annotation-name bmk))
+ (select-frame-set-input-focus oframe)))))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Make it a command (added `interactive' spec).
+;; 2. Use `bookmark-maybe-load-default-file', to ensure bookmarks are loaded.
+;; 3. Use name `*Bookmark Annotations*', not `*Bookmark Annotation*'.
+;; 4. Don't list bookmarks that have no annotation.
+;; 5. Highlight bookmark names. Don't indent annotations. Add a blank line after each annotation.
+;; 6. Use `view-mode'. `q' uses `quit-window'.
+;; 7. Fit frame to buffer if `one-windowp'.
+;; 8. Restore frame selection.
+;;
+;;;###autoload (autoload 'bookmark-show-all-annotations "bookmark+")
+(defun bookmark-show-all-annotations () ; Bound to `C-x x a S'
+ "Display the annotations for all bookmarks.
+If called from buffer `*Bookmark List*' then the annotations are shown
+in the current sort order."
+ (interactive)
+ (bookmark-maybe-load-default-file)
+ (let ((obuf (current-buffer))
+ (oframe (selected-frame)))
+ (save-selected-window
+ (pop-to-buffer (get-buffer-create "*Bookmark Annotations*"))
+ (let ((buffer-read-only nil)) ; Because buffer might already exist, in view mode.
+ (delete-region (point-min) (point-max))
+ ;; (Could use `bmkp-annotated-alist-only' here instead.)
+ (dolist (full-record (if (equal (buffer-name obuf) bmkp-bmenu-buffer)
+ (bmkp-sort-omit bookmark-alist
+ (and (not (eq bmkp-bmenu-filter-function
+ 'bmkp-omitted-alist-only))
+ bmkp-bmenu-omitted-bookmarks))
+ bookmark-alist))
+ (let ((ann (bookmark-get-annotation full-record)))
+ (when (and ann (not (string-equal ann "")))
+ (insert (concat (bmkp-bookmark-name-from-record full-record) ":\n"))
+ (put-text-property (line-beginning-position 0) (line-end-position 0) 'face 'bmkp-heading)
+ (insert ann) (unless (bolp) (insert "\n\n")))))
+ (goto-char (point-min))
+ (if (> emacs-major-version 23) ; Incompatible change introduced in Emacs 24.1
+ (view-mode-enter)
+ (view-mode-enter (cons (selected-window) (cons nil 'quit-window))))
+ (when (fboundp 'fit-frame-if-one-window) (fit-frame-if-one-window))))
+ (select-frame-set-input-focus oframe)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Save menu-list state to `bmkp-bmenu-state-file'.
+;;
+(defun bookmark-exit-hook-internal () ; This goes on `kill-emacs-hook'.
+ "Save currently defined bookmarks and perhaps bookmark menu-list state.
+Run `bookmark-exit-hook', then save bookmarks if they were updated.
+Then save menu-list state to file `bmkp-bmenu-state-file', but only if
+that option is non-nil."
+ (run-hooks 'bookmark-exit-hook)
+ (when (bookmark-time-to-save-p t)
+ (condition-case err ; Do NOT raise error. (Need to be able to exit.)
+ (bookmark-save)
+ (error (if (fboundp 'display-warning)
+ (display-warning 'bookmark-plus (error-message-string err))
+ (message (error-message-string err))
+ (sit-for 4))
+ nil)))
+ (bmkp-save-menu-list-state))
+
+;;(@* "Bookmark+ Functions (`bmkp-*')")
+;;; Bookmark+ Functions (`bmkp-*') -----------------------------------
+
+
+;;(@* "Filter Functions")
+;; *** Filter Functions ***
+
+(put 'bmkp-all-tags-alist-only 'bmkp-read-arg 'bmkp-read-tags-completing)
+(defun bmkp-all-tags-alist-only (tags)
+ "`bookmark-alist', but with only bookmarks having all their tags in TAGS.
+Does not include bookmarks that have no tags.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lambda (bmk)
+ (lexical-let* ((tgs tags)
+ (bmk-tags (bmkp-get-tags bmk)))
+ (and bmk-tags (bmkp-every (lambda (tag) (member (bmkp-tag-name tag) tgs)) bmk-tags))))
+ bookmark-alist))
+
+(put 'bmkp-all-tags-regexp-alist-only 'bmkp-read-arg 'bmkp-read-regexp)
+(defun bmkp-all-tags-regexp-alist-only (regexp)
+ "`bookmark-alist', but with only bookmarks having all tags match REGEXP.
+Does not include bookmarks that have no tags.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((rg regexp))
+ (lambda (bmk)
+ (let ((bmk-tags (bmkp-get-tags bmk)))
+ (and bmk-tags
+ (bmkp-every (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag))) bmk-tags)))))
+ bookmark-alist))
+
+(defun bmkp-annotated-alist-only ()
+ "`bookmark-alist', but only for bookmarks with non-empty annotations.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-annotated-bookmark-p bookmark-alist))
+
+(defun bmkp-autofile-alist-only (&optional prefix)
+ "`bookmark-alist', filtered to retain only autofile bookmarks.
+With non-nil arg PREFIX, the bookmark names must all have that PREFIX."
+ (bookmark-maybe-load-default-file)
+ (if (not prefix)
+ (bmkp-remove-if-not #'bmkp-autofile-bookmark-p bookmark-alist)
+ (bmkp-remove-if-not (lexical-let ((pref prefix)) (lambda (bmk) (bmkp-autofile-bookmark-p bmk pref)))
+ bookmark-alist)))
+
+(put 'bmkp-autofile-all-tags-alist-only 'bmkp-read-arg 'bmkp-read-tags-completing)
+(defun bmkp-autofile-all-tags-alist-only (tags)
+ "`bookmark-alist', with only autofiles having all tags in TAGS.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((tgs tags))
+ (lambda (bmk)
+ (and (bmkp-autofile-bookmark-p bmk) (bmkp-get-tags bmk)
+ (bmkp-every (lexical-let ((bk bmk)) (lambda (tag) (bmkp-has-tag-p bk tag))) tgs))))
+ bookmark-alist))
+
+(put 'bmkp-autofile-all-tags-regexp-alist-only 'bmkp-read-arg 'bmkp-read-regexp)
+(defun bmkp-autofile-all-tags-regexp-alist-only (regexp)
+ "`bookmark-alist', with only autofiles having all tags match REGEXP.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((rg regexp))
+ (lambda (bmk)
+ (and (bmkp-autofile-bookmark-p bmk)
+ (let ((bmk-tags (bmkp-get-tags bmk)))
+ (and bmk-tags
+ (bmkp-every (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag))) bmk-tags))))))
+ bookmark-alist))
+
+(put 'bmkp-autofile-some-tags-alist-only 'bmkp-read-arg 'bmkp-read-tags-completing)
+(defun bmkp-autofile-some-tags-alist-only (tags)
+ "`bookmark-alist', with only autofiles having some tags in TAGS.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lambda (bmk) (and (bmkp-autofile-bookmark-p bmk)
+ (bmkp-some (lexical-let ((bk bmk)) (lambda (tag) (bmkp-has-tag-p bk tag))) tags)))
+ bookmark-alist))
+
+(put 'bmkp-autofile-some-tags-regexp-alist-only 'bmkp-read-arg 'bmkp-read-regexp)
+(defun bmkp-autofile-some-tags-regexp-alist-only (regexp)
+ "`bookmark-alist', with only autofiles having some tags match REGEXP.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((rg regexp))
+ (lambda (bmk) (and (bmkp-autofile-bookmark-p bmk)
+ (bmkp-some (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag)))
+ (bmkp-get-tags bmk)))))
+ bookmark-alist))
+(defun bmkp-autonamed-alist-only ()
+ "`bookmark-alist', with only autonamed bookmarks (from any buffers).
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-autonamed-bookmark-p bookmark-alist))
+
+(defun bmkp-autonamed-this-buffer-alist-only ()
+ "`bookmark-alist', with only autonamed bookmarks for the current buffer.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lambda (bmk) (bmkp-autonamed-this-buffer-bookmark-p bmk)) bookmark-alist))
+
+(defun bmkp-bookmark-file-alist-only ()
+ "`bookmark-alist', filtered to retain only bookmark-file bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-bookmark-file-bookmark-p bookmark-alist))
+
+(defun bmkp-bookmark-list-alist-only ()
+ "`bookmark-alist', filtered to retain only bookmark-list bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-bookmark-list-bookmark-p bookmark-alist))
+
+(defun bmkp-buffer-alist-only ()
+ "`bookmark-alist', filtered to retain only non-file buffer bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-buffer-bookmark-p bookmark-alist))
+
+(defun bmkp-desktop-alist-only ()
+ "`bookmark-alist', filtered to retain only desktop bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-desktop-bookmark-p bookmark-alist))
+
+(defun bmkp-dired-alist-only ()
+ "`bookmark-alist', filtered to retain only Dired bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-dired-bookmark-p bookmark-alist))
+
+(defun bmkp-dired-this-dir-alist-only ()
+ "`bookmark-alist', with only Dired bookmarks for the current directory.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-dired-this-dir-bookmark-p bookmark-alist))
+
+(defun bmkp-dired-wildcards-alist-only ()
+ "`bookmark-alist', with only bookmarks for a Dired buffer with wildcards.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-dired-wildcards-bookmark-p bookmark-alist))
+
+(when (fboundp 'bmkp-eww-bookmark-p) ; Emacs 25+
+
+ (defun bmkp-eww-alist-only ()
+ "`bookmark-alist', filtered to retain only EWW bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-eww-bookmark-p bookmark-alist))
+
+ )
+
+(defun bmkp-file-alist-only ()
+ "`bookmark-alist', filtered to retain only file and directory bookmarks.
+This excludes bookmarks that might contain file information but are
+particular in some way - for example, Info bookmarks or Gnus bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-file-bookmark-p bookmark-alist))
+
+(put 'bmkp-file-all-tags-alist-only 'bmkp-read-arg 'bmkp-read-tags-completing)
+(defun bmkp-file-all-tags-alist-only (tags)
+ "`bookmark-alist', with only file bookmarks having all tags in TAGS.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((tgs tags))
+ (lambda (bmk)
+ (and (bmkp-file-bookmark-p bmk) (bmkp-get-tags bmk)
+ (bmkp-every (lexical-let ((bk bmk)) (lambda (tag) (bmkp-has-tag-p bk tag))) tgs))))
+ bookmark-alist))
+
+(put 'bmkp-file-all-tags-regexp-alist-only 'bmkp-read-arg 'bmkp-read-regexp)
+(defun bmkp-file-all-tags-regexp-alist-only (regexp)
+ "`bookmark-alist', with only file bookmarks having all tags match REGEXP.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((rg regexp))
+ (lambda (bmk)
+ (and (bmkp-file-bookmark-p bmk)
+ (let ((bmk-tags (bmkp-get-tags bmk)))
+ (and bmk-tags
+ (bmkp-every (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag))) bmk-tags))))))
+ bookmark-alist))
+
+(put 'bmkp-file-some-tags-alist-only 'bmkp-read-arg 'bmkp-read-tags-completing)
+(defun bmkp-file-some-tags-alist-only (tags)
+ "`bookmark-alist', with only file bookmarks having some tags in TAGS.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((tgs tags))
+ (lambda (bmk) (and (bmkp-file-bookmark-p bmk)
+ (bmkp-some (lexical-let ((bk bmk)) (lambda (tag) (bmkp-has-tag-p bk tag))) tgs))))
+ bookmark-alist))
+
+(put 'bmkp-file-some-tags-regexp-alist-only 'bmkp-read-arg 'bmkp-read-regexp)
+(defun bmkp-file-some-tags-regexp-alist-only (regexp)
+ "`bookmark-alist', with only file bookmarks having some tags match REGEXP.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((rg regexp))
+ (lambda (bmk) (and (bmkp-file-bookmark-p bmk)
+ (bmkp-some (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag)))
+ (bmkp-get-tags bmk)))))
+ bookmark-alist))
+
+(defun bmkp-file-this-dir-alist-only ()
+ "`bookmark-alist', filtered with `bmkp-file-this-dir-bookmark-p'.
+Include only files and subdir that are in `default-directory'.
+This excludes bookmarks that might contain file information but are
+particular in some way - for example, Info bookmarks or Gnus bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-file-this-dir-bookmark-p bookmark-alist))
+
+(put 'bmkp-file-this-dir-all-tags-alist-only 'bmkp-read-arg 'bmkp-read-tags-completing)
+(defun bmkp-file-this-dir-all-tags-alist-only (tags)
+ "`bookmark-alist', for files in this dir having all tags in TAGS.
+Include only files and subdir that are in `default-directory'.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((tgs tags))
+ (lambda (bmk)
+ (and (bmkp-file-this-dir-bookmark-p bmk) (bmkp-get-tags bmk)
+ (bmkp-every (lexical-let ((bk bmk)) (lambda (tag) (bmkp-has-tag-p bk tag))) tgs))))
+ bookmark-alist))
+
+(put 'bmkp-file-this-dir-all-tags-regexp-alist-only 'bmkp-read-arg 'bmkp-read-regexp)
+(defun bmkp-file-this-dir-all-tags-regexp-alist-only (regexp)
+ "`bookmark-alist', for files in this dir having all tags match REGEXP.
+Include only files and subdir that are in `default-directory'.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((rg regexp))
+ (lambda (bmk)
+ (and (bmkp-file-this-dir-bookmark-p bmk)
+ (let ((bmk-tags (bmkp-get-tags bmk)))
+ (and bmk-tags
+ (bmkp-every (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag))) bmk-tags))))))
+ bookmark-alist))
+
+(put 'bmkp-file-this-dir-some-tags-alist-only 'bmkp-read-arg 'bmkp-read-tags-completing)
+(defun bmkp-file-this-dir-some-tags-alist-only (tags)
+ "`bookmark-alist', for files in this dir having some tags in TAGS.
+Include only files and subdir that are in `default-directory'.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((tgs tags))
+ (lambda (bmk) (and (bmkp-file-this-dir-bookmark-p bmk)
+ (bmkp-some (lexical-let ((bk bmk)) (lambda (tag) (bmkp-has-tag-p bk tag))) tgs))))
+ bookmark-alist))
+
+(put 'bmkp-file-this-dir-some-tags-regexp-alist-only 'bmkp-read-arg 'bmkp-read-regexp)
+(defun bmkp-file-this-dir-some-tags-regexp-alist-only (regexp)
+ "`bookmark-alist', for files in this dir having some tags match REGEXP.
+Include only files and subdir that are in `default-directory'.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lexical-let ((rg regexp))
+ (lambda (bmk) (and (bmkp-file-this-dir-bookmark-p bmk)
+ (bmkp-some (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag)))
+ (bmkp-get-tags bmk)))))
+ bookmark-alist))
+
+(defun bmkp-function-alist-only ()
+ "`bookmark-alist', filtered to retain only function bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-function-bookmark-p bookmark-alist))
+
+(defun bmkp-gnus-alist-only ()
+ "`bookmark-alist', filtered to retain only Gnus bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-gnus-bookmark-p bookmark-alist))
+
+(defun bmkp-icicles-search-hits-alist-only ()
+ "`bookmark-alist', but only for Icicles search hits bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-icicles-search-hits-bookmark-p bookmark-alist))
+
+(defun bmkp-image-alist-only ()
+ "`bookmark-alist', filtered to retain only image-file bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-image-bookmark-p bookmark-alist))
+
+(defun bmkp-info-alist-only ()
+ "`bookmark-alist', filtered to retain only Info bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-info-bookmark-p bookmark-alist))
+
+(defun bmkp-last-specific-buffer-alist-only ()
+ "`bookmark-alist', but only for `bmkp-last-specific-buffer'.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-last-specific-buffer-p bookmark-alist))
+
+(defun bmkp-last-specific-file-alist-only ()
+ "`bookmark-alist', but only for `bmkp-last-specific-file'.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-last-specific-file-p bookmark-alist))
+
+(defun bmkp-man-alist-only ()
+ "`bookmark-alist', filtered to retain only `man' page bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-man-bookmark-p bookmark-alist))
+
+(defun bmkp-local-file-alist-only ()
+ "`bookmark-alist', filtered to retain only local-file bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-local-file-bookmark-p bookmark-alist))
+
+(defun bmkp-local-non-dir-file-alist-only ()
+ "`bookmark-alist', filtered to retain only local non-dir file bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-local-non-dir-file-bookmark-p bookmark-alist))
+
+(defun bmkp-marked-bookmarks-only ()
+ "Return the list of marked bookmarks."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-marked-bookmark-p bookmark-alist))
+
+(defun bmkp-non-autonamed-alist-only ()
+ "`bookmark-alist', with only non-autonamed bookmarks (from any buffers).
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lambda (bmk) (not (bmkp-autonamed-bookmark-p bmk))) bookmark-alist))
+
+(defun bmkp-non-dir-file-alist-only ()
+ "`bookmark-alist', filtered to retain only nondirectory file bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-non-dir-file-bookmark-p bookmark-alist))
+
+(defun bmkp-non-file-alist-only ()
+ "`bookmark-alist', filtered to retain only non-file bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-non-file-bookmark-p bookmark-alist))
+
+(defun bmkp-non-invokable-alist-only ()
+ "`bookmark-alist', filtered to retain only non-invokable bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-non-invokable-bookmark-p bookmark-alist))
+
+(defun bmkp-omitted-alist-only ()
+ "`bookmark-alist', filtered to retain only the omitted bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-omitted-bookmark-p bookmark-alist))
+
+(defun bmkp-omitted-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is an omitted bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+ (unless (stringp bookmark) (setq bookmark (bmkp-bookmark-name-from-record bookmark)))
+ (bmkp-bookmark-name-member bookmark bmkp-bmenu-omitted-bookmarks))
+
+(defun bmkp-orphaned-file-alist-only ()
+ "`bookmark-alist', filtered to retain only orphaned file bookmarks."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-orphaned-file-bookmark-p bookmark-alist))
+
+(defun bmkp-orphaned-local-file-alist-only ()
+ "`bookmark-alist', but retaining only orphaned local-file bookmarks."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-orphaned-local-file-bookmark-p bookmark-alist))
+
+(defun bmkp-orphaned-remote-file-alist-only ()
+ "`bookmark-alist', but retaining only orphaned remote-file bookmarks."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-orphaned-remote-file-bookmark-p bookmark-alist))
+
+(defun bmkp-regexp-filtered-annotation-alist-only ()
+ "`bookmark-alist' for annotations matching `bmkp-bmenu-filter-pattern'."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not
+ (lambda (bmk)
+ (let ((annot (bookmark-get-annotation bmk)))
+ (and (stringp annot) (not (string= "" annot))
+ (bmkp-string-match-p bmkp-bmenu-filter-pattern annot))))
+ bookmark-alist)) ; (Could use `bmkp-annotated-alist-only' here instead.)
+
+(defun bmkp-regexp-filtered-bookmark-name-alist-only ()
+ "`bookmark-alist' for bookmarks matching `bmkp-bmenu-filter-pattern'."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lambda (bmk)
+ (bmkp-string-match-p bmkp-bmenu-filter-pattern (bookmark-name-from-full-record bmk)))
+ bookmark-alist))
+
+(defun bmkp-regexp-filtered-file-name-alist-only ()
+ "`bookmark-alist' for files matching `bmkp-bmenu-filter-pattern'."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lambda (bmk) (let ((fname (bookmark-get-filename bmk)))
+ (and fname (bmkp-string-match-p bmkp-bmenu-filter-pattern fname))))
+ bookmark-alist))
+
+(defun bmkp-regexp-filtered-tags-alist-only ()
+ "`bookmark-alist' for tags matching `bmkp-bmenu-filter-pattern'."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lambda (bmk)
+ (let ((bmk-tags (bmkp-get-tags bmk)))
+ (and bmk-tags (bmkp-some (lambda (tag)
+ (bmkp-string-match-p bmkp-bmenu-filter-pattern
+ (bmkp-tag-name tag)))
+ bmk-tags))))
+ bookmark-alist))
+
+(defun bmkp-region-alist-only ()
+ "`bookmark-alist', filtered to retain only bookmarks that have regions.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-region-bookmark-p bookmark-alist))
+
+(defun bmkp-remote-file-alist-only ()
+ "`bookmark-alist', filtered to retain only remote-file bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-remote-file-bookmark-p bookmark-alist))
+
+(defun bmkp-remote-non-dir-file-alist-only ()
+ "`bookmark-alist', filtered to retain only remote non-dir file bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-remote-non-dir-file-bookmark-p bookmark-alist))
+
+(defun bmkp-sequence-alist-only ()
+ "`bookmark-alist', filtered to retain only sequence bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-sequence-bookmark-p bookmark-alist))
+
+(defun bmkp-snippet-alist-only ()
+ "`bookmark-alist', filtered to retain only snippet bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-snippet-bookmark-p bookmark-alist))
+
+(put 'bmkp-some-tags-alist-only 'bmkp-read-arg 'bmkp-read-tags-completing)
+(defun bmkp-some-tags-alist-only (tags)
+ "`bookmark-alist', but with only bookmarks having some tags in TAGS.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lexical-let ((tgs tags))
+ (lambda (bmk)
+ (bmkp-some (lexical-let ((bk bmk)) (lambda (tag) (bmkp-has-tag-p bk tag)))
+ tgs)))
+ bookmark-alist))
+
+(put 'bmkp-some-tags-regexp-alist-only 'bmkp-read-arg 'bmkp-read-regexp)
+(defun bmkp-some-tags-regexp-alist-only (regexp)
+ "`bookmark-alist', but with only bookmarks having some tags match REGEXP.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lexical-let ((rg regexp))
+ (lambda (bmk)
+ (bmkp-some (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag)))
+ (bmkp-get-tags bmk))))
+ bookmark-alist))
+
+(put 'bmkp-specific-buffers-alist-only 'bmkp-read-arg 'bmkp-read-buffers)
+(defun bmkp-specific-buffers-alist-only (&optional buffers)
+ "`bookmark-alist', filtered to retain only bookmarks to buffers BUFFERS.
+BUFFERS is a list of buffer names.
+It defaults to a singleton list with the current buffer's name.
+A new list is returned (no side effects).
+
+Note: Bookmarks created by vanilla Emacs do not record the buffer
+name. They are therefore excluded from the returned alist."
+ (unless buffers (setq buffers (list (buffer-name))))
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lexical-let ((bufs buffers))
+ (lambda (bmk)
+ (and (not (bmkp-desktop-bookmark-p bmk)) ; Exclude these
+ (not (bmkp-bookmark-file-bookmark-p bmk))
+ (not (bmkp-sequence-bookmark-p bmk))
+ (not (bmkp-function-bookmark-p bmk))
+ (not (bmkp-variable-list-bookmark-p bmk))
+ (member (bmkp-get-buffer-name bmk) bufs))))
+ bookmark-alist))
+
+(put 'bmkp-specific-files-alist-only 'bmkp-read-arg 'bmkp-read-files)
+(defun bmkp-specific-files-alist-only (&optional files)
+ "`bookmark-alist', filtered to retain only bookmarks to files FILES.
+FILES is a list of absolute file names.
+It defaults to a singleton list with the current buffer's file name,
+ or to the empty list if the buffer is not visiting a file.
+A new list is returned (no side effects)."
+ (unless files (setq files (and (buffer-file-name) (list (buffer-file-name)))))
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lexical-let ((ff files))
+ (lambda (bmk)
+ (let ((bf (bookmark-get-filename bmk)))
+ (and bf
+ ;; If we loaded `cl-seq.el': (cl-member bf ff :test #'bmkp-same-file-p)
+ (catch 'bmkp-specific-files-alist-only
+ (dolist (f ff)
+ (or (bmkp-same-file-p f bf) (throw 'bmkp-specific-files-alist-only nil)))
+ t)))))
+ bookmark-alist))
+
+(defun bmkp-tagged-alist-only ()
+ "`bookmark-alist', with only bookmarks that have tags.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-get-tags bookmark-alist))
+
+(defun bmkp-temporary-alist-only ()
+ "`bookmark-alist', filtered to retain only temporary bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-temporary-bookmark-p bookmark-alist))
+
+(defun bmkp-this-file/buffer-alist-only ()
+ "`bookmark-alist', with only bookmarks for the current file/buffer.
+A new list is returned (no side effects).
+If visiting a file, this is `bmkp-this-file-alist-only'.
+Otherwise, this is `bmkp-this-buffer-alist-only'."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (if (buffer-file-name) #'bmkp-this-file-p #'bmkp-this-buffer-p) bookmark-alist))
+
+(defun bmkp-this-buffer-alist-only ()
+ "`bookmark-alist', with only bookmarks for the current buffer.
+A new list is returned (no side effects).
+See `bmkp-this-buffer-p'."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-this-buffer-p bookmark-alist))
+
+(defun bmkp-this-file-alist-only ()
+ "`bookmark-alist', with only bookmarks for the current file.
+A new list is returned (no side effects).
+See `bmkp-this-file-p'."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-this-file-p bookmark-alist))
+
+(defun bmkp-unmarked-bookmarks-only ()
+ "Return the list of unmarked bookmarks."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if #'bmkp-marked-bookmark-p bookmark-alist))
+
+(defun bmkp-untagged-alist-only ()
+ "`bookmark-alist', with only bookmarks that do not have tags.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if #'bmkp-get-tags bookmark-alist))
+
+(defun bmkp-url-alist-only ()
+ "`bookmark-alist', filtered to retain only URL bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-url-bookmark-p bookmark-alist))
+
+(defun bmkp-url-browse-alist-only ()
+ "`bookmark-alist', but with only URL bookmarks that are non-W3M, non-EWW.
+\(The bookmarks satisfy `bmkp-url-browse-bookmark-p'.)
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-url-browse-bookmark-p bookmark-alist))
+
+(defun bmkp-variable-list-alist-only ()
+ "`bookmark-alist', filtered to retain only variable-list bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-variable-list-bookmark-p bookmark-alist))
+
+(defun bmkp-w3m-alist-only ()
+ "`bookmark-alist', filtered to retain only W3M bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not #'bmkp-w3m-bookmark-p bookmark-alist))
+
+;; This provides the `defvar's for all Bookmark+ history variables.
+;; Use this again, after you define any of your own filter functions
+;; `bmkp-*-alist-only', for new kinds of bookmarks.
+;;
+(bmkp-define-history-variables) ; Macro defined in `bookmark+-mac.el'.
+
+
+;;(@* "Miscellaneous Bookmark+ Functions")
+;; *** Miscellaneous Bookmark+ Functions ***
+
+(if (fboundp 'find-tag-default-as-regexp)
+ (defun bmkp-read-regexp (&optional prompt defaults history)
+ "Same as `read-regexp', except argument PROMPT is optional.
+PROMPT defaults to \"Regexp: \"."
+ (unless prompt (setq prompt "Regexp: "))
+ (read-regexp prompt defaults history))
+
+ ;; Same as `icicle-find-tag-default-as-regexp' in `icicles-fn.el'.
+ (defun bmkp-find-tag-default-as-regexp () ; Emacs < 24.3
+ "Return a regexp that matches the default tag at point.
+If there is no tag at point, return nil.
+
+When in a major mode that does not provide its own
+`find-tag-default-function', return a regexp that matches the
+symbol at point exactly."
+ (let* ((tagf (or find-tag-default-function
+ (get major-mode 'find-tag-default-function)
+ 'find-tag-default))
+ (tag (funcall tagf)))
+ (and tag (if (eq tagf 'find-tag-default)
+ (format "\\_<%s\\_>" (regexp-quote tag))
+ (regexp-quote tag)))))
+
+ ;; Same as `icicle-read-regexp' in `icicles-fn.el'.
+ (if (fboundp 'find-tag-default)
+ (defun bmkp-read-regexp (&optional prompt default history) ; Emacs 22-24.2
+ "Read and return a regular expression as a string.
+If PROMPT does not end with a colon and possibly whitespace then
+append \": \" to it.
+
+PROMPT defaults to \"Regexp: \".
+
+Optional argument DEFAULT is a string or a list of the form
+\(DEFLT . SUGGESTIONS), where DEFLT is a string or nil.
+
+The string DEFAULT or DEFLT is added to the prompt and is returned as
+the default value if the user enters empty input. The empty string is
+returned if DEFAULT or DEFLT is nil and the user enters empty input.
+
+SUGGESTIONS is used only for Emacs 23 and later. It is a list of
+strings that can be inserted into the minibuffer using `\\<minibuffer-local-map>\\[next-history-element]'.
+The values supplied in SUGGESTIONS are prepended to the list of
+standard suggestions, which include the tag at point, the last isearch
+regexp, the last isearch string, and the last replacement regexp.
+
+Optional argument HISTORY is a symbol to use for the history list.
+If nil then use `regexp-history'."
+ (unless prompt (setq prompt "Regexp: "))
+ (let* ((deflt (if (consp default) (car default) default))
+ (suggestions (and (> emacs-major-version 22)
+ (if (listp default) default (list default))))
+ (suggestions (and (> emacs-major-version 22)
+ (append
+ suggestions
+ (list (bmkp-find-tag-default-as-regexp)
+ (car regexp-search-ring)
+ (regexp-quote (or (car search-ring) ""))
+ (car (symbol-value query-replace-from-history-variable))))))
+ (suggestions (and (> emacs-major-version 22)
+ (delete-dups (delq nil (delete "" suggestions)))))
+ (history-add-new-input nil) ; Do not automatically add default to history for empty input.
+ (input (read-from-minibuffer
+ (cond ((bmkp-string-match-p ":[ \t]*\\'" prompt) prompt)
+ (deflt (format "%s (default %s): " prompt
+ (query-replace-descr deflt)))
+ (t (format "%s: " prompt)))
+ nil nil nil (or history 'regexp-history) suggestions t)))
+ (if (equal input "")
+ (or deflt input) ; Return the default value when the user enters empty input.
+ (prog1 input ; Add non-empty input to the history and return input.
+ (add-to-history (or history 'regexp-history) input)))))
+
+ (defun bmkp-read-regexp (&optional prompt default history) ; Emacs 20-21
+ "Read and return a string.
+PROMPT defaults to \"Regexp: \".
+Optional arg DEFAULT is a string that is returned when the user enters
+empty input. It can also be a list of strings, of which only the
+first is used.
+Optional arg HISTORY is a symbol to use for the history list. If nil,
+use `regexp-history'."
+ (unless prompt (setq prompt "Regexp: "))
+ (when (consp default) (setq default (car default)))
+ (read-string (cond ((bmkp-string-match-p ":[ \t]*\\'" prompt) prompt)
+ (default (format "%s (default %s): " prompt
+ (mapconcat #'isearch-text-char-description default "")))
+ (t (format "%s: " prompt)))
+ nil (or history 'regexp-history) default))))
+
+;; Same as `icicle-propertize'. (Not used yet.)
+;;
+(defun bmkp-propertize (object &rest properties)
+ "Like `propertize', but for all Emacs versions.
+If OBJECT is not a string, then use `prin1-to-string' to get a string."
+ (let ((new (if (stringp object) (copy-sequence object) (prin1-to-string object))))
+ (add-text-properties 0 (length new) properties new)
+ new))
+
+(defun bmkp-new-bookmark-default-names (&optional first-def)
+ "Return a list of default names (strings) for a new bookmark.
+A non-nil optional arg FIRST-DEF is prepended to the list of names
+described below.
+
+If the region is active and non-empty, then the first default name
+\(other than FIRST-DEF) is the current buffer name followed by \": \"
+and the region prefix (up to `bmkp-bookmark-name-length-max' chars).
+The other names are as described below.
+
+Uses option `bmkp-new-bookmark-default-names' to come up with the
+other names. To these names, `bookmark-current-bookmark' and
+`bookmark-buffer-name' are appended, if available (non-nil).
+
+NOTE: For Emacs versions prior to Emacs 23, return only a single
+default name, not a list of names. The name is the first in the list
+of names described above for Emacs 23+."
+ (let ((defs (and first-def (list first-def)))
+ val)
+ (unless (and (< emacs-major-version 23) defs) ; Just use FIRST-DEF for Emacs < 23.
+ ;; If region is active, first default is its text, with buffer name prepended.
+ (when (and transient-mark-mode mark-active (> (region-end) (region-beginning)))
+ (let* ((regname (concat (buffer-name) ": " (buffer-substring (region-beginning) (region-end))))
+ (defname (bmkp-replace-regexp-in-string
+ "\n" " "
+ (progn (save-excursion (goto-char (region-beginning))
+ (skip-chars-forward " ")
+ (setq bookmark-yank-point (point)))
+ (substring regname 0 (min bmkp-bookmark-name-length-max
+ (length regname)))))))
+ (if (< emacs-major-version 23) (setq defs defname) (add-to-list 'defs defname))))
+ ;; Names provided by option `bmkp-new-bookmark-default-names',
+ ;; plus `bookmark-current-bookmark' and `bookmark-buffer-name'.
+ (unless (and (< emacs-major-version 23) defs)
+ (catch 'bmkp-new-bookmark-default-names
+ (dolist (fn bmkp-new-bookmark-default-names)
+ (when (functionp fn) ; Be sure it is defined and is a function.
+ (setq val (funcall fn))
+ (when (and (stringp val) (not (string= "" val)))
+ (setq val (bmkp-replace-regexp-in-string "\n" " " val))
+ (if (> emacs-major-version 22)
+ (add-to-list 'defs val)
+ (throw 'bmkp-new-bookmark-default-names (setq defs val)))))))
+ (when (and (< emacs-major-version 23) (null defs))
+ (setq defs (or bookmark-current-bookmark (bookmark-buffer-name))))
+ (when (listp defs)
+ (when bookmark-current-bookmark (push bookmark-current-bookmark defs))
+ (let ((buf (bookmark-buffer-name))) (when buf (push buf defs)))
+ (setq defs (nreverse defs)))))
+ defs))
+
+(defun bmkp-bookmark-record-from-name (bookmark-name &optional noerror memp alist)
+ "Return the full bookmark (record) that corresponds to BOOKMARK-NAME.
+BOOKMARK-NAME must be a string. If it has non-nil text property
+`bmkp-full-record' then use that. Otherwise, look for the first
+bookmark in ALIST that has the given name.
+
+Non-nil optional arg NOERROR means return nil if BOOKMARK-NAME does
+not name a valid bookmark or is valid but is not in ALIST. If NOERROR
+is nil then raise an error in this case.
+
+Non-nil optional arg MEMP means that if property `bmkp-full-record' is
+available then look up its value (the full bookmark) in ALIST, testing
+with `eq'. If that record is not in ALIST, return nil.
+
+Optional arg ALIST defaults to `bookmark-alist'."
+ (unless alist (setq alist bookmark-alist))
+ (let ((full (get-text-property 0 'bmkp-full-record bookmark-name)))
+ (or (and full
+ (or (not memp) (memq full alist))
+ full)
+ ;; Punt: return first matching bookmark in ALIST.
+ (if (fboundp 'assoc-string) ; Emacs 22+. Use `assoc-string' for its CASE-FOLD arg.
+ (assoc-string bookmark-name alist bookmark-completion-ignore-case)
+ (assoc bookmark-name alist))
+ (and (not noerror) (error "No such bookmark in bookmark list: `%s'" bookmark-name)))))
+
+(defun bmkp-rename-for-marked-and-omitted-lists (old new)
+ "Replace OLD bookmark name with NEW in marked and omitted lists."
+ (when (bmkp-marked-bookmark-p old)
+ (setq bmkp-bmenu-marked-bookmarks (bmkp-delete-bookmark-name-from-list old
+ bmkp-bmenu-marked-bookmarks))
+ (push new bmkp-bmenu-marked-bookmarks))
+ (when (bmkp-omitted-bookmark-p old)
+ (setq bmkp-bmenu-omitted-bookmarks (bmkp-delete-bookmark-name-from-list old
+ bmkp-bmenu-omitted-bookmarks))
+ (push new bmkp-bmenu-omitted-bookmarks)))
+
+(defun bmkp-get-bookmark-in-alist (bookmark &optional noerror alist)
+ "Return the full bookmark in ALIST that corresponds to BOOKMARK.
+Return nil if there is none.
+BOOKMARK is a bookmark name or a bookmark record.
+
+Non-nil optional arg NOERROR means return nil if BOOKMARK does not
+represent a valid bookmark or is valid but is not in ALIST. If
+NOERROR is nil then raise an error in this case.
+
+Optional arg ALIST defaults to `bookmark-alist'.
+
+Bookmark membership in ALIST is tested using `eq'.
+
+If BOOKMARK is a bookmark name instead of a full bookmark then return
+what `bmkp-bookmark-record-from-name' with non-nil arg MEMP returns.
+
+This function is like `bookmark-get-bookmark', except that
+`bookmark-get-bookmark' tests whether BOOKMARK is in `bookmark-alist'
+only when it is a string (a bookmark name, not a full bookmark). When
+BOOKMARK is a full bookmark `bookmark-get-bookmark' is thus not a test
+for its existence, as is `bmkp-get-bookmark-in-alist'."
+ (cond ((consp bookmark) (and (memq bookmark (or alist bookmark-alist)) bookmark))
+ ((stringp bookmark) (bmkp-bookmark-record-from-name bookmark noerror 'MEMP alist))
+ (t (and (not noerror) (error "Invalid bookmark: `%s'" bookmark)))))
+
+(defun bmkp-default-bookmark-file ()
+ "`bmkp-last-as-first-bookmark-file', or `bookmark-default-file' if nil."
+ (or bmkp-last-as-first-bookmark-file bookmark-default-file))
+
+(defun bmkp-completing-read-bookmarks (&optional alist pred hist names-only-p use-nil-alist-p)
+ "Read bookmark names and return the bookmarks named as a list.
+You are prompted for each bookmark name. Hit `RET' with empty input
+to end.
+
+ALIST is the bookmark alist to use. It defaults to `bookmark-alist'
+unless USE-NIL-ALIST-P is non-nil.
+
+NAMES-ONLY-P non-nil means return bookmark names, not full bookmarks.
+If NAMES-ONLY-P is `lax' then completion is lax.
+
+USE-NIL-ALIST-P means do not default ALIST to `bookmark-alist': if
+ALIST is nil there are no bookmark candidates, so just return nil."
+ (let ((bmks ())
+ (bmk t))
+ (if (and use-nil-alist-p (not alist))
+ ()
+ (while bmk
+ (setq bmk (bmkp-completing-read-1 "Bookmark (RET for each, empty input to finish)"
+ "" alist pred hist (eq names-only-p 'lax)))
+ (when (equal "" bmk) (setq bmk nil))
+ (when (and bmk (not names-only-p)) (setq bmk (bmkp-get-bookmark-in-alist bmk 'NO-ERROR alist)))
+ (when bmk (push bmk bmks)))
+ (setq bmks (nreverse bmks))
+ bmks)))
+
+(defun bmkp-completing-read-lax (prompt &optional default alist pred hist use-nil-alist-p)
+ "Read a bookmark name, prompting with PROMPT.
+Like `bookmark-completing-read', but completion is lax (non-strict):
+your input need not match any existing bookmark name.
+
+In addition:
+ * You can use `SPC' and `?' freely when typing the name.
+ * You can use `C-M-w' repeatedly to yank consecutive words from the
+ current buffer (see `bookmark-yank-word')."
+ (let ((orig-C-M-w (lookup-key minibuffer-local-completion-map (kbd "C-M-w")))
+ (orig-C-M-u (lookup-key minibuffer-local-completion-map (kbd "C-M-u")))
+ (orig-SPC (lookup-key minibuffer-local-completion-map (kbd "SPC")))
+ (orig-qmark (lookup-key minibuffer-local-completion-map (kbd "?"))))
+ (unwind-protect
+ (progn (define-key minibuffer-local-completion-map (kbd "C-M-w") 'bookmark-yank-word)
+ (define-key minibuffer-local-completion-map (kbd "C-M-u") 'bookmark-insert-current-bookmark)
+ (unless (and (boundp 'icicle-mode) icicle-mode
+ (eq orig-SPC 'icicle-self-insert))
+ (define-key minibuffer-local-completion-map (kbd "SPC") 'self-insert-command))
+ (unless (and (boundp 'icicle-mode) icicle-mode
+ (eq orig-qmark 'icicle-self-insert))
+ (define-key minibuffer-local-completion-map (kbd "?") 'self-insert-command))
+ (bmkp-completing-read-1 prompt default alist pred hist 'LAX use-nil-alist-p))
+ (define-key minibuffer-local-completion-map (kbd "C-M-w") orig-C-M-w)
+ (define-key minibuffer-local-completion-map (kbd "C-M-u") orig-C-M-u)
+ (define-key minibuffer-local-completion-map (kbd "SPC") orig-SPC)
+ (define-key minibuffer-local-completion-map (kbd "?") orig-qmark))))
+
+(defun bmkp-completing-read-1 (prompt &optional default alist pred hist laxp use-nil-alist-p)
+ "Helper for functions that read a bookmark name with completion.
+See `bookmark-completing-read' for the argument descriptions."
+ (bookmark-maybe-load-default-file)
+ (unless (or alist use-nil-alist-p) (setq alist bookmark-alist))
+ (if (and (not laxp)
+ (listp last-nonmenu-event)
+ (or (eq t bmkp-menu-popup-max-length)
+ (and (integerp bmkp-menu-popup-max-length) (< (length alist) bmkp-menu-popup-max-length))))
+ (bookmark-menu-popup-paned-menu
+ t prompt
+ (if bmkp-sort-comparer ; Test whether to sort, but always use `string-lessp'.
+ (sort (bookmark-all-names alist) 'string-lessp)
+ (bookmark-all-names alist)))
+ (let* ((icicle-delete-candidate-object (lambda (cand) ; For `S-delete' in Icicles.
+ (bookmark-delete (icicle-transform-multi-completion cand))))
+ (icicle-bookmark-completing-p t)
+ (completion-ignore-case bookmark-completion-ignore-case)
+ (default (and (not (equal "" default)) default)) ; Treat "" like nil.
+ (default (if (and (consp default) (< emacs-major-version 23))
+ (car default)
+ default))
+ (prompt (concat prompt (if default
+ (format " (%s): " (if (consp default)
+ (car default)
+ default))
+ ": ")))
+ (str (completing-read prompt alist pred (not laxp) nil
+ (or hist 'bookmark-history) default)))
+ str)))
+
+(defun bmkp-jump-1 (bookmark display-function &optional flip-use-region-p)
+ "Helper function for `bookmark-jump' commands.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a bookmark name then it is looked up in `bookmark-alist'.
+If it is a record then it is NOT looked up (need not belong).
+If it is or has a name that has non-nil property `bmkp-full-record',
+then use the bookmark in `bookmark-alist' that is the value of that
+property. Raise no error if it has no name.
+
+DISPLAY-FUNCTION as in `bmkp-jump'. Passed to `bookmark--jump-via'.
+Non-nil optional arg FLIP-USE-REGION-P means temporarily flip the
+ value of `bmkp-use-region'."
+ (setq bookmark (bmkp-get-bookmark bookmark 'NOERROR))
+ (unless bookmark (error "No bookmark specified"))
+ (run-hooks 'bmkp-before-jump-hook)
+ (bookmark-maybe-historicize-string (bmkp-bookmark-name-from-record bookmark))
+ (let ((bmkp-use-region (if flip-use-region-p (not bmkp-use-region) bmkp-use-region)))
+ (bookmark--jump-via bookmark display-function)))
+
+(defun bmkp-select-buffer-other-window (buffer)
+ "Select BUFFER in another window.
+If `bmkp-other-window-pop-to-flag' is non-nil, then use
+`pop-to-buffer'. Otherwise, use `switch-to-buffer-other-window'."
+ (if bmkp-other-window-pop-to-flag (pop-to-buffer buffer t) (switch-to-buffer-other-window buffer)))
+
+(defun bmkp-maybe-save-bookmarks (&optional same-count-p)
+ "Increment save counter and maybe save `bookmark-alist'.
+Non-nil optional arg SAME-COUNT-P means do not increment
+`bookmark-alist-modification-count'."
+ (unless same-count-p (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count)))
+ (when (bookmark-time-to-save-p) (bookmark-save)))
+
+;;;###autoload (autoload 'bmkp-annotate-bookmark "bookmark+")
+(defun bmkp-annotate-bookmark (bookmark) ; Bound to `C-x x a a'
+ "Annotate BOOKMARK. Pop up a buffer to add or edit the annotation.
+Interactively, this is the same as using command
+`bookmark-edit-annotation' with a prefix arg. You are prompted for
+the bookmark name. Command `bookmark-edit-annotation' can be more
+convenient for editing an existing annotation, because you choose
+among only the already annotated bookmarks, not all bookmarks.
+
+Non-interactively, BOOKMARK is a bookmark name or a bookmark record."
+ (interactive (list (bookmark-completing-read "Annotate bookmark" (bmkp-default-bookmark-name))))
+ (pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*"))
+ (bookmark-insert-annotation bookmark)
+ (bookmark-edit-annotation-mode)
+ (setq bookmark-annotation-name bookmark))
+
+;;;###autoload (autoload 'bmkp-annotate-bookmark-this-file/buffer "bookmark+")
+(defun bmkp-annotate-bookmark-this-file/buffer (bookmark) ; Bound to `C-x x a b'
+ "Annotate an existing bookmark in this file or buffer.
+You are prompted for the name of a bookmark here, with completion."
+ (interactive
+ (let ((alist (bmkp-this-file/buffer-alist-only)))
+ (list (bookmark-completing-read (format "%s annotation for bookmark"
+ (if current-prefix-arg "Add or edit" "Edit"))
+ (or (and (fboundp 'bmkp-bookmarks-lighted-at-point)
+ (bmkp-bookmarks-lighted-at-point))
+ (bmkp-default-bookmark-name alist))
+ alist
+ nil
+ nil
+ (not current-prefix-arg)))))
+ (bookmark-edit-annotation bookmark))
+
+;;;###autoload (autoload 'bmkp-annotate-all-bookmarks-this-file/buffer "bookmark+")
+(defun bmkp-annotate-all-bookmarks-this-file/buffer () ; Bound to `C-x x a B'
+ "Pop up annotation-editing buffer for each bookmark in this file/buffer."
+ (interactive)
+ (dolist (bmk (bmkp-this-file/buffer-alist-only))
+ (bookmark-edit-annotation bmk)))
+
+;;;###autoload (autoload 'bmkp-show-this-annotation-read-only "bookmark+")
+(defun bmkp-show-this-annotation-read-only ()
+ "Switch to `Show Bookmark Annotation' mode for this annotation.
+That is, switch from edit mode to read-only mode."
+ (interactive)
+ (unless (eq major-mode 'bookmark-edit-annotation-mode)
+ (error "Buffer is not in `Edit Bookmark Annotation' mode"))
+ (if (not (or (not (buffer-modified-p)) (y-or-n-p "Annotation was modified. Lose changes?")))
+ (message "OK, canceled - use `C-c C-c' if you want to save changes")
+ (let* ((bmk (bmkp-get-bookmark bookmark-annotation-name 'NOERROR))
+ (bname (bookmark-name-from-full-record bmk))
+ (ann (and bmk (bookmark-get-annotation bmk)))
+ (obuf (current-buffer)))
+ (unless bname (error "No such bookmark: `%s'" bmk))
+ (bmkp--pop-to-buffer-same-window (format "*`%s' Annotation*" bname))
+ (let ((buffer-read-only nil) ; Because buffer might already exist, in view mode.
+ (buf-modified-p (buffer-modified-p)))
+ (delete-region (point-min) (point-max))
+ (insert (concat "Annotation for bookmark '" bname "':\n\n"))
+ ;; Use `font-lock-ignore' property from library `font-lock+.el', because Org mode
+ ;; uses font-lock, which would otherwise wipe out the highlighting added here.
+ (add-text-properties (line-beginning-position -1) (line-end-position 1)
+ '(face bmkp-heading
+ font-lock-ignore t))
+ (insert ann)
+ (set-buffer-modified-p buf-modified-p))
+ (goto-char (point-min))
+ (bookmark-show-annotation-mode)
+ (when (fboundp 'fit-frame-if-one-window) (fit-frame-if-one-window))
+ (setq bookmark-annotation-name bmk)
+ (kill-buffer obuf))))
+
+;;;###autoload (autoload 'bmkp-edit-this-annotation "bookmark+")
+(defun bmkp-edit-this-annotation ()
+ "Switch to `Edit Bookmark Annotation' mode for this annotation.
+That is, switch from read-only mode to edit mode."
+ (interactive)
+ (unless (eq major-mode 'bookmark-show-annotation-mode)
+ (error "Buffer is not in `Show Bookmark Annotation' mode"))
+ (let* ((bmk (bmkp-get-bookmark bookmark-annotation-name 'NOERROR))
+ (bname (bookmark-name-from-full-record bmk))
+ (obuf (current-buffer)))
+ (unless bname (error "No such bookmark: `%s'" bmk))
+ (bmkp--pop-to-buffer-same-window (generate-new-buffer-name "*Bookmark Annotation Compose*"))
+ (let ((buf-modified-p (buffer-modified-p)))
+ (bookmark-insert-annotation bname)
+ (set-buffer-modified-p buf-modified-p))
+ (bookmark-edit-annotation-mode)
+ (when (fboundp 'fit-frame-if-one-window) (fit-frame-if-one-window))
+ (setq bookmark-annotation-name bmk)
+ (kill-buffer obuf)))
+
+;;;###autoload (autoload 'bmkp-copy-bookmark "bookmark+")
+(defalias 'bmkp-copy-bookmark 'bmkp-clone-bookmark)
+;;;###autoload (autoload 'bmkp-clone-bookmark "bookmark+")
+(defun bmkp-clone-bookmark (bookmark &optional clone confirm-overwrite-p)
+ ; Bound to `C-x x 2' (`M-n' in bookmark list)
+ "Duplicate BOOKMARK to produce a clone.
+The clone name is the same as BOOKMARK, but with \"<2>\" appended.
+With a prefix arg you are instead prompted for the clone name.
+
+When called from Lisp:
+ * BOOKMARK is a bookmark name or a bookmark record.
+ * Optional CLONE is the clone name.
+ * Optional non-nil CONFIRM-OVERWRITE-P means prompt to confirm overwriting an existing bookmark."
+ (interactive
+ (let* ((orig (bookmark-completing-read "Clone bookmark" (bmkp-default-bookmark-name)))
+ ;; Remove any `bmkp-full-record' property from name.
+ (_IGNORE (remove-text-properties 0 (length orig) '(bmkp-full-record nil) orig))
+ (default (concat orig "<2>"))
+ (new (if current-prefix-arg
+ (bmkp-completing-read-lax "Clone name" default)
+ default)))
+ (while (equal orig new)
+ (setq new (bmkp-completing-read-lax "Clone name (must be different)" default)))
+ ;; Remove any `bmkp-full-record' property from name.
+ (remove-text-properties 0 (length new) '(bmkp-full-record nil) new)
+ (list orig new t)))
+ (let ((orig-bmk (bmkp-get-bookmark bookmark))
+ (new-bmk (bmkp-get-bookmark clone 'NO-ERROR)))
+ (when (and new-bmk confirm-overwrite-p)
+ (unless (yes-or-no-p "Another bookmark with that name already exists. Overwrite it? ")
+ (error "OK; canceled")))
+ (setq new-bmk (copy-sequence orig-bmk))
+ ;; Get rid of old bookmark name, which might have property `bmkp-full-record'.
+ ;; Need to do that before calling `bookmark-store'.
+ (setcar new-bmk clone)
+ (bookmark-store clone (cdr new-bmk) nil) ; (Puts `bmkp-full-record' on name.)
+ (setq bookmark-current-bookmark clone)
+ (if (and (get-buffer bmkp-bmenu-buffer) (get-buffer-window (get-buffer bmkp-bmenu-buffer) 0))
+ (with-current-buffer (get-buffer bmkp-bmenu-buffer)
+ (bmkp-refresh-menu-list clone))
+ (bookmark-bmenu-surreptitiously-rebuild-list))
+ (bmkp-maybe-save-bookmarks)))
+
+;;;###autoload (autoload 'bmkp-edit-bookmark-name-and-location "bookmark+")
+(defun bmkp-edit-bookmark-name-and-location (bookmark &optional edit-record-p)
+ ; Bound to `C-x x r' (`r' in bookmark list)
+ "Edit BOOKMARK's name and location, and maybe save them.
+Return a list of the new bookmark name and new location.
+BOOKMARK is a bookmark name or a bookmark record.
+
+Without a prefix arg, you are prompted for the new bookmark name and
+ the new location name. When entering the new names you can use
+ completion against existing names. This completion is lax, so you
+ can easily edit an existing name. See `bookmark-set' for particular
+ keys available during this input.
+
+With a prefix arg, edit the complete bookmark record (the
+ internal, Lisp form)."
+ (interactive
+ (list (bookmark-completing-read (concat "Edit " (and current-prefix-arg "internal record for ")
+ "bookmark")
+ (bmkp-default-bookmark-name))
+ current-prefix-arg))
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark))
+ (if edit-record-p
+ (bmkp-edit-bookmark-record bookmark)
+ (let* ((bmk-name (bmkp-bookmark-name-from-record bookmark))
+ (bmk-location (bookmark-prop-get bookmark 'location))
+ (bmk-urlp (and bmk-location
+ (require 'ffap nil t)
+ (ffap-url-p bmk-location)))
+ (bmk-filename (bookmark-get-filename bmk-name))
+ (bmk-buffname (or (bmkp-get-buffer-name bookmark)
+ (bookmark-prop-get bookmark 'buffer)))
+ (new-bmk-name (bmkp-completing-read-lax
+ "New bookmark name" bmk-name))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (new-location
+ (cond (bmk-location
+ (cond ((not bmk-urlp) (read-string "New location: "))
+ ((and (featurep 'w3m) (bmkp-w3m-bookmark-p bmk-name))
+ (w3m-input-url "New URL: " bmk-location))
+ ((and (fboundp 'bmkp-eww-bookmark-p) (bmkp-eww-bookmark-p bmk-name))
+ (read-string "New URL: "))
+ ((require 'ffap) (ffap-read-file-or-url "New URL: " bmk-location))
+ (t (read-string "New location: "))))
+ (bmk-filename
+ (if (and (featurep 'w3m)
+ (bmkp-w3m-bookmark-p bmk-name))
+ (w3m-input-url "New url: " bmk-filename)
+ (read-file-name
+ "New file name (location): "
+ (and bmk-filename
+ (file-name-directory bmk-filename))
+ bmk-filename)))
+ (bmk-buffname
+ (read-buffer "New location: " bmk-buffname))
+ (t ; No current location.
+ (read-string "New location: "))))
+ ;; $$$$$$ Should we change a W3M bookmark that uses `filename' to use `location' instead?
+ (changed-bmk-name-p (and (not (equal new-bmk-name ""))
+ (not (equal new-bmk-name bmk-name))))
+ (changed-location-p (and bmk-location
+ (not (equal new-location ""))
+ (not (equal new-location bmk-location))))
+ (changed-filename-p (and bmk-filename
+ (not (equal new-location ""))
+ (not (equal new-location bmk-filename))))
+ (changed-buffname-p (and bmk-buffname
+ (not (equal new-location ""))
+ (not (equal new-location bmk-buffname))
+ (not (and (fboundp 'bmkp-eww-bookmark-p)
+ (bmkp-eww-bookmark-p bookmark))))))
+ (when (or changed-bmk-name-p changed-location-p changed-filename-p changed-buffname-p)
+ (when changed-bmk-name-p (bookmark-rename bmk-name new-bmk-name 'BATCHP))
+ (when changed-location-p (bookmark-prop-set new-bmk-name 'location new-location))
+ (when changed-filename-p (bookmark-set-filename new-bmk-name new-location))
+ (when changed-buffname-p (bookmark-prop-set new-bmk-name 'buffer-name new-location))
+ ;; Change location for Dired too, but not if different from original file name (e.g. a cons).
+ (let ((dired-dir (bookmark-prop-get new-bmk-name 'dired-directory)))
+ (when (and dired-dir (equal dired-dir bmk-filename))
+ (bookmark-prop-set new-bmk-name 'dired-directory new-location)))
+ (bmkp-maybe-save-bookmarks) ; Maybe save automatically.
+ (when (and bookmark-alist-modification-count ; Did not save automatically. Ask user.
+ (y-or-n-p "Save changes? "))
+ (bookmark-save))
+ (list new-bmk-name new-location)))))
+
+(define-derived-mode bmkp-edit-bookmark-records-mode emacs-lisp-mode
+ "Edit Bookmark Records"
+ "Mode for editing a list of bookmark records, as in `bookmark-alist'.
+When you finish editing, use \\<bmkp-edit-bookmark-record-mode-map>\
+`\\[bmkp-edit-bookmark-record-send]' in the record-editing buffer."
+ :group 'bookmark-plus)
+
+;; This binding must be defined *after* the mode, so `bmkp-edit-bookmark-records-mode-map' is defined.
+;; (Alternatively, we could use a `defvar' to define `bmkp-edit-bookmark-records-mode-map' before
+;; calling `define-derived-mode'.)
+(define-key bmkp-edit-bookmark-records-mode-map "\C-c\C-c" 'bmkp-edit-bookmark-records-send)
+
+(defvar bmkp-edit-bookmark-records-number 0
+ "NUmber of bookmard records being edited.")
+
+;;;###autoload (autoload 'bmkp-edit-bookmark-records-send "bookmark+")
+(defun bmkp-edit-bookmark-records-send (&optional msg-p) ; Bound to `C-c C-c' in records-editing buffer.
+ "Update `bookmark-alist' with buffer contents: a bookmark alist.
+Lines beginning with `;;' are ignored.
+Non-interactively, optional arg MSG-P means display progress messages.
+
+This assumes that the bookmarks in the buffer are the marked bookmarks
+in `*Bookmark List*'. That is, it assumes that the buffer was created
+by `bmkp-bmenu-edit-marked' (`\\<bookmark-bmenu-mode-map>\\[bmkp-bmenu-edit-marked]' in `*Bookmark List*')."
+ (interactive "p")
+ (unless (eq major-mode 'bmkp-edit-bookmark-records-mode)
+ (error "Not in `bmkp-edit-bookmark-records-mode'"))
+ (when msg-p (message "Reading edited bookmarks..."))
+ (let* ((editbuf (current-buffer))
+ (orig-bmks (bmkp-marked-bookmarks-only))
+ (edited-bookmarks ())
+ (read-error-msg
+ (catch 'bmkp-edit-bookmark-records-send
+ (setq edited-bookmarks (condition-case err
+ (save-excursion (goto-char (point-min)) (read (current-buffer)))
+ (error (throw 'bmkp-edit-bookmark-records-send
+ (error-message-string err)))))
+ (unless orig-bmks (error "No marked bookmarks now - edits must correspond to currently marked"))
+ (cond ((not (listp edited-bookmarks))
+ (throw 'bmkp-edit-bookmark-records-send "Not a list of bookmarks"))
+ ((not (= (length edited-bookmarks) bmkp-edit-bookmark-records-number))
+ (throw 'bmkp-edit-bookmark-records-send
+ (format "Need %d bookmarks, but there seem to be %d"
+ bmkp-edit-bookmark-records-number (length edited-bookmarks)))))
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save only after `dolist' and update.
+ (dolist (edited-bmk edited-bookmarks)
+ (unless (and (consp edited-bmk) (stringp (car edited-bmk))) ; Sanity check.
+ (throw 'bmkp-edit-bookmark-records-send (format "Invalid bookmark: `%s'" edited-bmk)))
+ (let ((bname (bmkp-bookmark-name-from-record edited-bmk))
+ (data (bmkp-bookmark-data-from-record edited-bmk)))
+ ;; Put the full bookmark on its name as property `bmkp-full-record'.
+ ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+ ;; If it needs to be stripped, that will be done when saving.
+ (put-text-property 0 (length bname) 'bmkp-full-record edited-bmk bname)
+ ;; Update the original bookmark (same cons cell) with what's in the edited version.
+ (setcar (car orig-bmks) bname)
+ (setcdr (car orig-bmks) data)
+ ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+ (unless (memq (car orig-bmks) bmkp-modified-bookmarks)
+ (setq bmkp-modified-bookmarks (cons (car orig-bmks) bmkp-modified-bookmarks)))
+ (setq orig-bmks (cdr orig-bmks))))
+ ;; Update using modified ORIG-BMKS.
+ (setq bmkp-bmenu-marked-bookmarks (mapcar #'bmkp-bookmark-name-from-record
+ bmkp-modified-bookmarks)
+ bmkp-sorted-alist (bmkp-sort-omit bookmark-alist)
+ bookmark-alist-modification-count (1+ bookmark-alist-modification-count)))
+ nil)))
+ (if (stringp read-error-msg)
+ (if msg-p (message "%s --> edit and try again" read-error-msg) (error read-error-msg))
+ (when (get-buffer editbuf) (kill-buffer editbuf))
+ (bmkp-refresh/rebuild-menu-list
+ (and (= 1 (length edited-bookmarks)) (car edited-bookmarks)) ; Only one, so we belong on its line.
+ (not msg-p)))))
+
+(define-derived-mode bmkp-edit-bookmark-record-mode emacs-lisp-mode
+ "Edit Bookmark Record"
+ "Mode for editing an internal bookmark record.
+When you finish editing, use \\<bmkp-edit-bookmark-record-mode-map>\
+`\\[bmkp-edit-bookmark-record-send]' in the record-editing buffer."
+ :group 'bookmark-plus)
+
+;; This binding must be defined *after* the mode, so `bmkp-edit-bookmark-record-mode-map' is defined.
+;; (Alternatively, we could use a `defvar' to define `bmkp-edit-bookmark-record-mode-map' before
+;; calling `define-derived-mode'.)
+(define-key bmkp-edit-bookmark-record-mode-map "\C-c\C-c" 'bmkp-edit-bookmark-record-send)
+
+;;;###autoload (autoload 'bmkp-edit-bookmark-record "bookmark+")
+(defun bmkp-edit-bookmark-record (bookmark) ; Bound to `C-x x E'.
+ "Edit the full record (the Lisp sexp) for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+When you finish editing, use \\<bmkp-edit-bookmark-record-mode-map>\
+`\\[bmkp-edit-bookmark-record-send]' in the record-editing buffer.
+The current bookmark list is then updated to reflect your edits."
+ (interactive (list (bookmark-completing-read "Edit Lisp record for bookmark" (bmkp-default-bookmark-name))))
+ (bookmark-maybe-load-default-file)
+ (setq bmkp-edit-bookmark-orig-record (bmkp-get-bookmark-in-alist bookmark))
+ (let* ((bmk-copy (copy-sequence bmkp-edit-bookmark-orig-record)) ; Shallow copy
+ (bname (bmkp-bookmark-name-from-record bmk-copy))
+ (bufname (format "*Edit Record for Bookmark `%s'*" bname)))
+ (set-text-properties 0 (length bname) nil bname) ; Strip properties from (copied) name string.
+ (bookmark-maybe-historicize-string bname)
+ (bmkp-with-output-to-plain-temp-buffer bufname
+ (princ
+ (substitute-command-keys
+ (concat ";; Edit the Lisp record for bookmark\n;;\n"
+ ";; `" bname "'\n;;\n"
+ ";; Type \\<bmkp-edit-bookmark-record-mode-map>\
+`\\[bmkp-edit-bookmark-record-send]' when done.\n;;\n")))
+ ;; (let ((print-circle t)) (pp bmk)) ; $$$$$$ Binding should not really be needed now.
+ (pp bmk-copy)
+ (goto-char (point-min)))
+ (pop-to-buffer bufname)
+ (buffer-enable-undo)
+ (with-current-buffer (get-buffer bufname) (bmkp-edit-bookmark-record-mode))))
+
+;;;###autoload (autoload 'bmkp-edit-bookmark-record-send "bookmark+")
+(defun bmkp-edit-bookmark-record-send (&optional msg-p) ; Bound to `C-c C-c' in record-editing buffer.
+ "Update `bookmark-alist' with buffer contents: a bookmark record.
+Lines beginning with `;;' are ignored.
+Non-interactively, optional arg MSG-P means display progress messages."
+ (interactive "p")
+ (unless (eq major-mode 'bmkp-edit-bookmark-record-mode)
+ (error "Not in `bmkp-edit-bookmark-record-mode'"))
+ (unless (and (boundp 'bmkp-edit-bookmark-orig-record) (consp bmkp-edit-bookmark-orig-record))
+ (error "Lost original bookmark record - try edit command again"))
+ (when msg-p (message "Reading edited bookmark..."))
+ (let* ((editbuf (current-buffer))
+ (bmk-name nil)
+ (read-error-msg
+ (catch 'bmkp-edit-bookmark-record-send
+ (let ((edited-bmk
+ (condition-case err
+ (save-excursion (goto-char (point-min)) (read (current-buffer)))
+ (error (throw 'bmkp-edit-bookmark-record-send (error-message-string err))))))
+ (unless (and (consp edited-bmk) (stringp (car edited-bmk)))
+ (throw 'bmkp-edit-bookmark-record-send (format "Invalid bookmark: `%s'" edited-bmk)))
+ (let ((bname (bmkp-bookmark-name-from-record edited-bmk))
+ (data (bmkp-bookmark-data-from-record edited-bmk)))
+ ;; Put the full bookmark on its name as property `bmkp-full-record'.
+ ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+ ;; If it needs to be stripped, that will be done when saving.
+ (put-text-property 0 (length bname) 'bmkp-full-record edited-bmk bname)
+ ;; Update the original bookmark with what's in the edited version.
+ (setcar bmkp-edit-bookmark-orig-record bname)
+ (setcdr bmkp-edit-bookmark-orig-record data)
+ ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+ (unless (memq bmkp-edit-bookmark-orig-record bmkp-modified-bookmarks)
+ (setq bmkp-modified-bookmarks (cons bmkp-edit-bookmark-orig-record
+ bmkp-modified-bookmarks)))
+ (setq bmk-name bname)) ; Save for bookmark-list display, below.
+ (setq bmkp-sorted-alist (bmkp-sort-omit bookmark-alist)
+ bookmark-alist-modification-count (1+ bookmark-alist-modification-count)))
+ nil)))
+ (if (stringp read-error-msg)
+ (if msg-p (message "%s --> edit and try again" read-error-msg) (error read-error-msg))
+ (when (get-buffer editbuf) (kill-buffer editbuf))
+ (bmkp-refresh/rebuild-menu-list bmk-name (not msg-p)))
+ (unless read-error-msg
+ (setq bmkp-edit-bookmark-orig-record nil)))) ; Reset it, but keep it if error so can try again.
+
+;;;###autoload (autoload 'bmkp-edit-bookmark-record-file/buffer "bookmark+")
+(defun bmkp-edit-bookmark-record-file/buffer (bookmark) ; Not bound
+ "Edit the full record (the Lisp sexp) of a bookmark in this buffer.
+You are prompted for the name of a bookmark here, with completion."
+ (interactive
+ (let ((alist (bmkp-this-file/buffer-alist-only)))
+ (list (bookmark-completing-read (format "%s annotation for bookmark"
+ (if current-prefix-arg "Add or edit" "Edit"))
+ (or (and (fboundp 'bmkp-bookmarks-lighted-at-point)
+ (bmkp-bookmarks-lighted-at-point))
+ (bmkp-default-bookmark-name alist))
+ alist
+ nil
+ nil
+ (not current-prefix-arg)))))
+ (bmkp-edit-bookmark-record bookmark))
+
+;;; ;;;###autoload (autoload 'bmkp-edit-all-bookmark-records-this-file/buffer "bookmark+")
+;;; (defun bmkp-edit-all-bookmark-records-this-file/buffer () ; Not bound
+;;; "Pop up a record-editing buffer for each bookmark in this file/buffer."
+;;; (interactive)
+;;; (dolist (bmk (bmkp-this-file/buffer-alist-only))
+;;; (bmkp-edit-bookmark-record bmk)))
+
+(define-derived-mode bmkp-edit-tags-mode emacs-lisp-mode
+ "Edit Bookmark Tags"
+ "Mode for editing bookmark tags.
+When you have finished composing, type \\[bmkp-edit-tags-send]."
+ :group 'bookmark-plus)
+
+;; This binding must be defined *after* the mode, so `bmkp-edit-tags-mode-map' is defined.
+;; (Alternatively, we could use a `defvar' to define `bmkp-edit-tags-mode-map' before
+;; calling `define-derived-mode'.)
+(define-key bmkp-edit-tags-mode-map "\C-c\C-c" 'bmkp-edit-tags-send)
+
+;;;###autoload (autoload 'bmkp-edit-tags "bookmark+")
+(defun bmkp-edit-tags (bookmark) ; Bound to `C-x x t e'
+ "Edit BOOKMARK's tags, and maybe save the result.
+The edited value must be a list each of whose elements is either a
+ string or a cons whose key is a string.
+BOOKMARK is a bookmark name or a bookmark record."
+ (interactive (list (bookmark-completing-read "Edit tags for bookmark" (bmkp-default-bookmark-name))))
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark))
+ (let* ((btags (bmkp-get-tags bookmark))
+ (bmkname (bmkp-bookmark-name-from-record bookmark))
+ (edbuf (format "*Edit Tags for Bookmark `%s'*" bmkname)))
+ (setq bmkp-return-buffer (current-buffer))
+ (bmkp-with-output-to-plain-temp-buffer edbuf
+ (princ
+ (substitute-command-keys
+ (concat ";; Edit tags for bookmark\n;;\n;; \"" bmkname "\"\n;;\n"
+ ";; The edited value must be a list each of whose elements is\n"
+ ";; either a string or a cons whose key is a string.\n;;\n"
+ ";; DO NOT MODIFY THESE COMMENTS.\n;;\n"
+ ";; Type \\<bmkp-edit-tags-mode-map>`\\[bmkp-edit-tags-send]' when done.\n\n")))
+ (let ((print-circle bmkp-propertize-bookmark-names-flag)
+ (print-gensym bmkp-propertize-bookmark-names-flag))
+ (pp btags))
+ (goto-char (point-min)))
+ (pop-to-buffer edbuf)
+ (buffer-enable-undo)
+ (with-current-buffer (get-buffer edbuf) (bmkp-edit-tags-mode))))
+
+;;;###autoload (autoload 'bmkp-edit-tags-send "bookmark+")
+(defun bmkp-edit-tags-send (&optional batchp)
+ "Use buffer contents as the internal form of a bookmark's tags.
+DO NOT MODIFY the header comment lines, which begin with `;;'."
+ (interactive)
+ (unless (eq major-mode 'bmkp-edit-tags-mode) (error "Not in `bmkp-edit-tags-mode'"))
+ (let (bname)
+ (unwind-protect
+ (let (tags bmk)
+ (goto-char (point-min))
+ (unless (search-forward ";; Edit tags for bookmark\n;;\n;; ")
+ (error "Missing header in edit buffer"))
+ (unless (stringp (setq bname (read (current-buffer))))
+ (error "Bad bookmark name in edit-buffer header"))
+ (unless (setq bmk (bmkp-get-bookmark-in-alist bname 'NOERROR))
+ (error "No such bookmark: `%s'" bname))
+ (goto-char (point-min))
+ (setq tags (read (current-buffer)))
+ (unless (listp tags) (error "Tags sexp is not a list of strings or an alist with string keys"))
+ (bookmark-prop-set bmk 'tags tags)
+ (setq bname (bmkp-bookmark-name-from-record bmk))
+ (bmkp-record-visit bmk batchp)
+ (bmkp-refresh/rebuild-menu-list bname batchp)
+ (bmkp-maybe-save-bookmarks)
+ (unless batchp (message "Updated bookmark file with edited tags")))
+ (kill-buffer (current-buffer)))
+ (when bmkp-return-buffer
+ (pop-to-buffer bmkp-return-buffer)
+ (when (equal (buffer-name (current-buffer)) bmkp-bmenu-buffer)
+ (bmkp-bmenu-goto-bookmark-named bname)))))
+
+(defun bmkp-record-visit (bookmark &optional batchp)
+ "Update the data recording a visit to BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+This increments the `visits' entry and sets the `time' entry to the
+current time. If either an entry is not present, it is added (with 0
+value for `visits').
+With non-nil optional arg BATCHP, do not rebuild the menu list.
+
+Although this function modifies BOOKMARK, it does not increment
+`bookmark-alist-modification-count', and it does not add BOOKMARK to
+`bmkp-modified-bookmarks'. This is so that simply recording the visit
+does not count toward needing to save or showing BOOKMARK as modified."
+ (let ((vis (bookmark-prop-get bookmark 'visits))
+ (bmkp-modified-bookmarks bmkp-modified-bookmarks))
+ (bookmark-prop-set bookmark 'visits (if vis (1+ vis) 0))
+ (bookmark-prop-set bookmark 'time (current-time))
+ (unless batchp (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P))
+ (let ((bookmark-save-flag nil)) (bmkp-maybe-save-bookmarks 'SAME-COUNT-P))))
+
+(defun bmkp-default-bookmark-name (&optional alist)
+ "Default bookmark name. See option `bmkp-default-bookmark-name'.
+Non-nil ALIST means return nil unless the default names a bookmark in
+ALIST."
+ (let ((bname (if (equal (buffer-name (current-buffer)) bmkp-bmenu-buffer)
+ (bookmark-bmenu-bookmark)
+ (if (fboundp 'bmkp-default-lighted)
+ (if (eq 'highlighted bmkp-default-bookmark-name)
+ (or (bmkp-default-lighted) bookmark-current-bookmark)
+ (or bookmark-current-bookmark (bmkp-default-lighted)))
+ bookmark-current-bookmark))))
+ (when (consp bname) (setq bname (car bname))) ; Since `bmkp-default-lighted' can return a list of names.
+ (when (and bname alist)
+ (setq bname (bmkp-bookmark-name-from-record (bmkp-bookmark-record-from-name
+ bname 'NOERROR 'MEMP alist))))
+ bname))
+
+(defun bmkp-buffer-names ()
+ "Buffer names used by existing bookmarks that really have buffers.
+This excludes buffers for bookmarks such as desktops that are not
+really associated with a buffer."
+ (let ((bufs ())
+ buf)
+ (dolist (bmk bookmark-alist)
+ (when (and (not (bmkp-desktop-bookmark-p bmk))
+ (not (bmkp-bookmark-file-bookmark-p bmk))
+ (not (bmkp-sequence-bookmark-p bmk))
+ (not (bmkp-function-bookmark-p bmk))
+ (not (bmkp-variable-list-bookmark-p bmk))
+ (setq buf (bmkp-get-buffer-name bmk)))
+ (add-to-list 'bufs buf)))
+ bufs))
+
+(defun bmkp-file-names ()
+ "The absolute file names used by the existing bookmarks.
+This excludes the pseudo file name `bmkp-non-file-filename'."
+ (let ((files ())
+ file)
+ (dolist (bmk bookmark-alist)
+ (when (and (setq file (bookmark-get-filename bmk)) (not (equal file bmkp-non-file-filename)))
+ (add-to-list 'files file)))
+ files))
+
+;;;###autoload (autoload 'bmkp-bookmark-set-confirm-overwrite "bookmark+")
+(defun bmkp-bookmark-set-confirm-overwrite (&optional name parg interactivep) ; Bound `C-x r m', `C-x x c m'.
+ "Set a bookmark named NAME, then run `bmkp-after-set-hook'.
+This is the same as `bookmark-set', except that with no prefix arg you
+are asked to confirm overwriting an existing bookmark of the same
+NAME."
+ (interactive (list nil current-prefix-arg t))
+ (let ((bmkp-bookmark-set-confirms-overwrite-p t))
+ (call-interactively #'bookmark-set)))
+
+;;;###autoload (autoload 'bmkp-send-bug-report "bookmark+")
+(defun bmkp-send-bug-report () ; Not bound
+ "Send a bug report about a Bookmark+ problem."
+ (interactive)
+ (browse-url (format (concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
+Bookmark+ bug: \
+&body=Describe bug below, using a precise recipe that starts with `emacs -Q' or `emacs -q'. \
+Be sure to mention the `Update #' from header of the particular Bookmark+ file header.\
+%%0A%%0AEmacs version: %s")
+ (emacs-version))))
+
+;;;###autoload (autoload 'bmkp-toggle-bookmark-set-refreshes "bookmark+")
+(defun bmkp-toggle-bookmark-set-refreshes () ; Not bound
+ "Toggle whether `bookmark-set' refreshes `bookmark-alist' as last filtered.
+Add/remove `bmkp-refresh-latest-bookmark-list' to/from
+`bmkp-after-set-hook'.
+\(Applies also to command `bmkp-bookmark-set-confirm-overwrite'.)"
+ (interactive)
+ (if (member 'bmkp-refresh-latest-bookmark-list bmkp-after-set-hook)
+ (remove-hook 'bmkp-after-set-hook 'bmkp-refresh-latest-bookmark-list)
+ (add-hook 'bmkp-after-set-hook 'bmkp-refresh-latest-bookmark-list)))
+
+(defun bmkp-refresh-latest-bookmark-list ()
+ "Refresh `bmkp-latest-bookmark-alist' to reflect `bookmark-alist'."
+ (setq bmkp-latest-bookmark-alist (if bmkp-bmenu-filter-function
+ (funcall bmkp-bmenu-filter-function)
+ bookmark-alist)))
+
+;;;###autoload (autoload 'bmkp-toggle-saving-menu-list-state "bookmark+")
+(defun bmkp-toggle-saving-menu-list-state () ; Bound to `C-M-~' in bookmark list
+ "Toggle the value of option `bmkp-bmenu-state-file'.
+Tip: You can use this before quitting Emacs, to not save the state.
+If the initial value of `bmkp-bmenu-state-file' is nil, then this
+command has no effect."
+ (interactive)
+ (unless (or bmkp-last-bmenu-state-file bmkp-bmenu-state-file)
+ (error "Cannot toggle: initial value of `bmkp-bmenu-state-file' is nil"))
+ (setq bmkp-last-bmenu-state-file (prog1 bmkp-bmenu-state-file
+ (setq bmkp-bmenu-state-file bmkp-last-bmenu-state-file)))
+ (message (if bmkp-bmenu-state-file
+ "Autosaving of bookmark list state is now ON"
+ "Autosaving of bookmark list state is now OFF")))
+
+;;;###autoload (autoload 'bmkp-save-menu-list-state "bookmark+")
+(defun bmkp-save-menu-list-state (&optional msg-p) ; Used in `bookmark-exit-hook-internal'.
+ "Save menu-list state, unless not saving or list has not yet been shown.
+The state is saved to the value of `bmkp-bmenu-state-file'.
+Non-interactively, optional arg MSG-P means display progress messages."
+ (interactive "p")
+ (when (and (not bmkp-bmenu-first-time-p) bmkp-bmenu-state-file)
+ (when msg-p (message "Saving bookmark-list display state..."))
+ (let ((config-list
+ `((last-sort-comparer . ,bmkp-sort-comparer)
+ (last-reverse-sort-p . ,bmkp-reverse-sort-p)
+ (last-reverse-multi-sort-p . ,bmkp-reverse-multi-sort-p)
+ (last-latest-bookmark-alist . ,(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-latest-bookmark-alist))
+ (last-bmenu-omitted-bookmarks . ,(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-omitted-bookmarks 'COPY))
+ (last-bmenu-marked-bookmarks . ,(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-marked-bookmarks 'COPY))
+ (last-bmenu-filter-function . ,bmkp-bmenu-filter-function)
+ (last-bmenu-filter-pattern . ,bmkp-bmenu-filter-pattern)
+ (last-bmenu-title . ,bmkp-bmenu-title)
+ (last-bmenu-bookmark . ,(and (get-buffer bmkp-bmenu-buffer)
+ (with-current-buffer
+ (get-buffer bmkp-bmenu-buffer)
+ (bmkp-maybe-unpropertize-string
+ (bookmark-bmenu-bookmark) 'COPY))))
+ ;; Use `copy-sequence' here just in case, to avoid circular references when
+ ;; `bmkp-propertize-bookmark-names-flag' is nil.
+ (last-specific-buffer . ,(copy-sequence bmkp-last-specific-buffer))
+ (last-specific-file . ,(copy-sequence bmkp-last-specific-file))
+ (last-bmenu-toggle-filenames . ,bookmark-bmenu-toggle-filenames)
+ (last-bmenu-before-hide-marked-alist . ,(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-before-hide-marked-alist 'COPY))
+ (last-bmenu-before-hide-unmarked-alist . ,(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-before-hide-unmarked-alist 'COPY))
+ (last-bookmark-file . ,(copy-sequence
+ (convert-standard-filename
+ (expand-file-name
+ bmkp-current-bookmark-file))))
+ (last-previous-bookmark-file . ,(and bmkp-last-bookmark-file
+ (copy-sequence
+ (convert-standard-filename
+ (expand-file-name
+ bmkp-last-bookmark-file))))))))
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect bmkp-bmenu-state-file))
+ (goto-char (point-min))
+ (delete-region (point-min) (point-max))
+ (let ((print-length nil)
+ (print-level nil)
+ (print-circle bmkp-propertize-bookmark-names-flag)
+ (print-gensym bmkp-propertize-bookmark-names-flag)
+ (version-control (case bookmark-version-control
+ ((nil) nil)
+ (never 'never)
+ (nospecial version-control)
+ (t t)))
+ (require-final-newline t)
+ (errorp nil))
+ (pp config-list (current-buffer))
+ (condition-case nil
+ (write-file bmkp-bmenu-state-file)
+ (file-error
+ (setq errorp t)
+ ;; Do NOT raise error - used in `bookmark-exit-hook-internal'. (Need to be able to exit.)
+ (let ((msg (format "CANNOT WRITE FILE `%s'" bmkp-bmenu-state-file)))
+ (if (fboundp 'display-warning)
+ (display-warning 'bookmark-plus msg)
+ (message msg)
+ (sit-for 4)))))
+ (kill-buffer (current-buffer))
+ (when (and msg-p (not errorp)) (message "Saving bookmark-list display state...done")))))))
+
+;;;###autoload (autoload 'bmkp-toggle-saving-bookmark-file "bookmark+")
+(defun bmkp-toggle-saving-bookmark-file (&optional msg-p) ; Bound to `M-~' in bookmark list
+ "Toggle the value of option `bookmark-save-flag'.
+If the initial value of `bookmark-save-flag' is nil, then this
+command has no effect.
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive "p")
+ (unless (or bmkp-last-save-flag-value bookmark-save-flag)
+ (error "Cannot toggle: initial value of `bookmark-save-flag' is nil"))
+ ;; One of the two vars should be nil. If both are non-nil, set `*-last-*' to nil before toggling.
+ (when (and bmkp-last-save-flag-value bookmark-save-flag) (setq bmkp-last-save-flag-value nil))
+ (setq bmkp-last-save-flag-value (prog1 bookmark-save-flag
+ (setq bookmark-save-flag bmkp-last-save-flag-value)))
+ (when msg-p (message (if bookmark-save-flag
+ "Autosaving of current bookmark file is now ON"
+ "Autosaving of current bookmark file is now OFF"))))
+
+;; Same as `read-from-whole-string' (called `thingatpt--read-from-whole-string' starting with Emacs 25)
+;; in library `thingatpt.el'.
+;;
+(defun bmkp-read-from-whole-string (string)
+ "Read a Lisp expression from STRING.
+Raise an error if the entire string was not used."
+ (let* ((read-data (read-from-string string))
+ (more-left (condition-case nil
+ ;; The call to `ignore' suppresses a compiler warning.
+ (progn (ignore (read-from-string (substring string (cdr read-data))))
+ t)
+ (end-of-file nil))))
+ (if more-left (error "Can't read whole string") (car read-data))))
+
+;;;###autoload (autoload 'bmkp-jump-to-list "bookmark+")
+(defun bmkp-jump-to-list (bookmark
+ &optional position msgp) ; Bound globally to `C-x j C-j', `C-x x C-j'
+ "Jump to BOOKMARK entry in `*Bookmark List*'.
+You are prompted for BOOKMARK (a bookmark name).
+If you use library `bookmark+-lit.el':
+ * The defaults for BOOKMARK are the lighted bookmarks at point.
+ * A prefix arg means only lighted bookmarks at point are candidates."
+ (interactive (let* ((litp (fboundp 'bmkp-bookmarks-lighted-at-point))
+ (lbmks (and litp (bmkp-bookmarks-lighted-at-point (point) nil 'MSG)))
+ (bmk (bookmark-completing-read (if current-prefix-arg "Lighted bookmark" "Bookmark")
+ (and litp (if current-prefix-arg (car lbmks) lbmks))
+ (and current-prefix-arg lbmks))))
+ (list bmk (point) t)))
+ (pop-to-buffer (get-buffer-create bmkp-bmenu-buffer))
+ (bookmark-bmenu-list)
+ (bmkp-bmenu-goto-bookmark-named (setq bmkp-last-bmenu-bookmark bookmark)))
+
+;;;###autoload (autoload 'bmkp-make-function-bookmark "bookmark+")
+(defun bmkp-make-function-bookmark (bookmark-name function &optional msg-p) ; Bound globally to `C-x x c F'.
+ "Create a bookmark that invokes FUNCTION when \"jumped\" to.
+You are prompted for the bookmark name and the name of the function.
+But with a prefix arg the last keyboard macro defined is used instead
+of prompting you for a function.
+
+Returns the new bookmark (internal record).
+
+Non-interactively, non-nil optional arg MSG-P means display a status
+message."
+ (interactive (let ((icicle-unpropertize-completion-result-flag t))
+ (list (bmkp-completing-read-lax "Bookmark")
+ (if (and current-prefix-arg last-kbd-macro)
+ (read-kbd-macro last-kbd-macro 'NEED-VECTOR)
+ (completing-read "Function: " obarray 'functionp))
+ 'MSG)))
+ (unless (or (functionp function) (vectorp function))
+ (setq function (bmkp-read-from-whole-string function))) ; Convert name to symbol.
+ (bookmark-store bookmark-name `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT 0 nil 'NO-REGION)
+ (function . ,function)
+ (handler . bmkp-jump-function))
+ nil nil (not msg-p))
+ (let ((new (bmkp-bookmark-record-from-name bookmark-name 'NOERROR)))
+ (unless (memq new bmkp-latest-bookmark-alist)
+ (setq bmkp-latest-bookmark-alist (cons new bmkp-latest-bookmark-alist)))
+ (bookmark-bmenu-surreptitiously-rebuild-list (not msg-p))
+ new))
+
+;;;###autoload (autoload 'bmkp-set-dired-bookmark-for-files "bookmark+")
+(defun bmkp-set-dired-bookmark-for-files (bookmark-name dired-name to-add &optional switches msg-p)
+ "Create a Dired bookmark for a set of files and directories.
+You are prompted for the Dired buffer name and the file or directory
+entries to include. With a prefix arg, you are also prompted for the
+`ls' switches.
+
+Use `C-g' when done choosing file and directory names. Any directory
+names you choose this way are included as single entries in the
+listing - the directory contents are not included. To instead include
+the contents of a directory, use a glob pattern: put `/*' after the
+directory name.
+
+You need library `Dired+' for this command."
+ (interactive
+ (let* ((_IGNORE (unless (require 'dired+ nil t)
+ (error "You need library `Dired+' for this command")))
+ (current-prefix-arg (if current-prefix-arg 0 -1))
+ (all (diredp-dired-union-interactive-spec
+ "add files/dirs "
+ 'NO-DIRED-BUFS
+ 'READ-EXTRA-FILES-P)))
+ (list (bmkp-completing-read-lax "Bookmark") (nth 0 all) (nth 3 all) (nth 2 all) 'MSG)))
+ (bmkp-make-function-bookmark
+ bookmark-name
+ `(lambda () (diredp-add-to-dired-buffer ',dired-name ',to-add ',switches))
+ msg-p))
+
+(when (boundp 'grep-history) ; Emacs 26+
+ (defun bmkp-set-grep-command-bookmark (bookmark-name &optional grep-cmd msg-p)
+ "Create a bookmark to run the last grep command.
+With a prefix arg, you are prompted for the grep command to record,
+ with lax completion against your previous `grep' inputs in this
+ session."
+ (interactive
+ (let ((parg current-prefix-arg))
+ (unless grep-history (error "Emacs command `grep' has not yet been run"))
+ (list (bmkp-completing-read-lax "Bookmark")
+ (and parg
+ (completing-read "Grep command: "
+ grep-history nil t nil 'grep-history (car grep-history)))
+ 'MSG)))
+ (setq grep-cmd (or grep-cmd (car grep-history)))
+ (unless (stringp grep-cmd) (error "Emacs command `grep' has not yet been run"))
+ (bmkp-make-function-bookmark bookmark-name
+ `(lambda () (funcall #'grep ,grep-cmd))
+ msg-p)))
+
+;;;###autoload (autoload 'bmkp-revert-bookmark-file "bookmark+")
+(defun bmkp-revert-bookmark-file (&optional msg-p) ; Same as `C-u g' in bookmark list (but not bound).
+ "Revert to the bookmarks in the current bookmark file.
+You are asked for confirmation.
+
+This DISCARDS all modifications to bookmarks and the bookmark list
+\(e.g. added/deleted bookmarks) since the last bookmark-file save.
+IOW, it reloads the bookmark file, overwriting the current bookmark
+list. This also removes any markings and omissions.
+
+This has the same effect as using `C-u \\<bookmark-bmenu-mode-map>\\[bmkp-bmenu-refresh-menu-list]' in \
+buffer `*Bookmark List*'.
+To refresh the display from the current bookmark list instead of the
+bookmark file, use just `\\[bmkp-bmenu-refresh-menu-list]' (no `C-u').
+
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive "p")
+ (when (and msg-p (not (yes-or-no-p (format "Revert to bookmarks saved in file `%s'? "
+ bmkp-current-bookmark-file))))
+ (error "OK - canceled"))
+ (bookmark-load bmkp-current-bookmark-file 'OVERWRITE msg-p) ; Do not let `bookmark-load' ask to save.
+ (bmkp-refresh/rebuild-menu-list nil (not msg-p)))
+
+;;;###autoload (autoload 'bmkp-switch-bookmark-file "bookmark+")
+(defun bmkp-switch-bookmark-file (file &optional batchp) ; Not bound and not used in the code now.
+ "Switch to a different bookmark file, FILE.
+Return FILE. Interactively, you are prompted for FILE.
+Replace all bookmarks in the current bookmark list with those from the
+newly loaded FILE. Bookmarks are subsequently saved to FILE.
+
+Optional arg BATCHP is passed to `bookmark-load'."
+ (interactive
+ (list (let* ((std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ bookmark-default-file
+ std-default)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Switch to bookmark file: "
+ (or (file-name-directory default) "~/")
+ default
+ t)))) ; Require that the file exist.
+ (bookmark-load file t batchp)) ; Treat it interactively, if this command is called interactively.
+
+;;;###autoload (autoload 'bmkp-switch-to-last-bookmark-file "bookmark+")
+(defun bmkp-switch-to-last-bookmark-file (&optional batchp) ; Not bound to key, but effectively `C-u C-x x L'
+ "Switch back to the last-used bookmark file.
+Replace all currently existing bookmarks with those newly loaded from
+the last-used file. Swap the values of `bmkp-last-bookmark-file' and
+`bmkp-current-bookmark-file'.
+
+Optional arg BATCHP is passed to `bookmark-load'."
+ (interactive)
+ (bookmark-load (or bmkp-last-bookmark-file (bmkp-default-bookmark-file))
+ t batchp)) ; Treat it interactively, if this command is called interactively.
+
+;;;###autoload (autoload 'bmkp-switch-bookmark-file-create "bookmark+")
+(defun bmkp-switch-bookmark-file-create (file &optional switch-to-lastp batchp)
+ ; Bound to `C-x x L', (`L' in bookmark list)
+ "Switch to bookmark file FILE, creating it as empty if it does not exist.
+With a prefix arg, switch to the last bookmark file used.
+Otherwise, you are prompted for FILE.
+
+Replace all bookmarks in the current bookmark list with those from the
+newly loaded file. Bookmarks are subsequently saved to that file.
+
+If there is no file with the name you provide (FILE), then create a
+new, empty bookmark file with that name and use that from now on.
+This empties the bookmark list. Interactively, you are required to
+confirm this.
+
+Return the newly current bookmark file.
+
+When called from Lisp:
+* FILE is the bookmark-file name or nil (meaning use the last one).
+* Non-nil BATCHP is passed to `bookmark-load'."
+ (interactive
+ (if current-prefix-arg
+ (list nil current-prefix-arg)
+ (list (let* ((std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ bookmark-default-file
+ std-default)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Switch to bookmark file: "
+ (or (file-name-directory default) "~/")
+ default))
+ nil)))
+ (if (not switch-to-lastp)
+ (let ((empty-p nil))
+ (if (file-readable-p file)
+;;; (if (or batchp (y-or-n-p (format "CONFIRM: `%s' as the current bookmark file? " file)))
+;;; (bookmark-load file t batchp)
+;;; (error "OK, canceled"))
+ (bookmark-load file t batchp) ; Treat it interactively, if this command is called interactively.
+ (setq empty-p t)
+ (when (and (not batchp)
+ (not (y-or-n-p (format "Create and use NEW, EMPTY bookmark file `%s'? " file))))
+ (error "OK - canceled"))
+ (bmkp-empty-file file)
+ (bookmark-load file t batchp)) ; Treat it interactively, if this command is called interactively.
+ (unless batchp (message "Bookmark file is now %s`%s'" (if empty-p "EMPTY file " "") file)))
+ (bmkp-switch-to-last-bookmark-file batchp)
+ (setq file bmkp-current-bookmark-file))
+ file)
+
+;;;###autoload (autoload 'bmkp-switch-to-bookmark-file-this-file/buffer "bookmark+")
+(defun bmkp-switch-to-bookmark-file-this-file/buffer (file &optional batchp) ; Bound to `C-x x C-l'
+ "Switch to a bookmark file for bookmarks in this file or buffer.
+If visiting a file, the bookmarks are ‘bmkp-this-file-alist-only’.
+Otherwise, they are ‘bmkp-this-buffer-alist-only’.
+
+If there are unsaved bookmarks in the current bookmark list you are
+first prompted to save it.
+
+You are then prompted for the bookmark file to switch to, for
+bookmarks only for this file/buffer."
+ (interactive
+ (list (let* ((std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ bookmark-default-file
+ std-default)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Switch to bookmark file for bookmarks here: "
+ (or (and default (file-name-directory default)) "~/")
+ default))))
+ (bmkp-switch-bookmark-file-create file))
+
+(defun bmkp-read-bookmark-file-name (&optional prompt dir default-filename require-match)
+ "Read and return an (absolute) bookmark file name.
+PROMPT is the prompt to use (default: \"Use bookmark file: \").
+The other args are the same as for `read-file-name'."
+ (let ((insert-default-directory t)
+ (icicle-unpropertize-completion-result-flag t)) ; For `read-file-name'.
+ (expand-file-name
+ (read-file-name (or prompt "Use bookmark file: ") dir default-filename require-match))))
+
+(defun bmkp-read-bookmark-file-default ()
+ "A default value for `bmkp-read-bookmark-file-name' DEFAULT-FILENAME arg.
+A value to use if you want a default and there is none better."
+ (if (and (> emacs-major-version 22)
+ (not (bmkp-same-file-p "~/.emacs.bmk" bookmark-default-file)))
+ (list "~/.emacs.bmk" bookmark-default-file)
+ "~/.emacs.bmk"))
+
+;;;###autoload (autoload 'bmkp-empty-file "bookmark+")
+(defun bmkp-empty-file (file &optional confirmp) ; Bound to `C-x x 0'
+ "Empty the bookmark file FILE, or create FILE (empty) if it does not exist.
+In either case, FILE will become an empty bookmark file. Return FILE.
+
+NOTE: If FILE already exists and you confirm emptying it, no check is
+ made that it is in fact a bookmark file before emptying it.
+ It is simply replaced by an empty bookmark file and saved.
+
+This does NOT also make FILE the current bookmark file. To do that,
+use `\\[bmkp-switch-bookmark-file-create]' (`bmkp-switch-bookmark-file-create').
+
+Interactively, and non-interactively if optional arg CONFIRMP is
+non-nil, require confirmation if the file already exists."
+ (interactive (list (let ((icicle-unpropertize-completion-result-flag t))
+ (read-file-name "Create empty bookmark file: " "~/"))
+ t))
+ (setq file (expand-file-name file))
+ (when (file-directory-p file) (error "`%s' is a directory, not a file" file))
+ (bookmark-maybe-load-default-file)
+ (when (and confirmp (file-exists-p file)
+ (not (y-or-n-p (format "CONFIRM: Empty the existing file `%s'? " file))))
+ (error "OK - canceled"))
+ (let ((bookmark-alist ()))
+ (bookmark-write-file file nil (if (file-exists-p file)
+ "Emptying bookmark file `%s'..."
+ "Creating new, empty bookmark file `%s'...")))
+ file)
+
+(defun bmkp-write-alist-bookmarks-to-file (alist file &optional addp)
+ "Write bookmarks in ALIST to FILE.
+By default, replace FILE with only the ALIST bookmarks.
+Non-nil ADDP means just add the bookmarks to those already in
+FILE (updating them if already present)."
+ (when (file-directory-p file) (error "`%s' is a directory, not a file" file))
+ (let ((bookmark-save-flag nil) ; Inhibit auto-saving for the duration.
+ (bookmark-alist bookmark-alist)
+ (bookmark-alist-modification-count bookmark-alist-modification-count)
+ imported)
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
+ (goto-char (point-min))
+ (if (file-exists-p file)
+ (bookmark-maybe-upgrade-file-format)
+ (delete-region (point-min) (point-max)) ; In case a find-file hook inserted a header etc.
+ (if (boundp 'bookmark-file-coding-system) ; Insert timestamp and an empty bookmark list.
+ (bookmark-insert-file-format-version-stamp bookmark-file-coding-system) ; Emacs 25.2+
+ (bookmark-insert-file-format-version-stamp))
+ (insert "(\n)"))
+ (let ((blist (bookmark-alist-from-buffer)))
+ (unless (listp blist) (error "Invalid bookmark list in file `%s'" file))
+ (setq bookmark-alist blist) ; Bookmarks in FILE
+ (setq imported (bookmark-import-new-list alist nil 'RETURN-BMKS))
+ (unless (and (zerop (nth 0 imported)) (zerop (nth 1 imported)))
+ (bookmark-write-file file))))))
+
+;;;###autoload (autoload 'bmkp-save-bookmarks-this-file/buffer "bookmark+")
+(defun bmkp-save-bookmarks-this-file/buffer (file &optional addp batchp) ; Bound to `C-x x C-s'
+ "Save bookmarks defined for the current file/buffer to FILE.
+If visiting a file, the bookmarks are ‘bmkp-this-file-alist-only’.
+Otherwise, they are ‘bmkp-this-buffer-alist-only’.
+
+You are prompted for FILE, the bookmark file to save to.
+
+By default, replace FILE with only the bookmarks for the current
+file/buffer. With a prefix arg, just add the bookmarks to those
+already in FILE (updating them if already present).
+
+This does NOT make FILE the current bookmark file. To do that, use
+`bmkp-switch-to-bookmark-file-this-file/buffer'."
+ (interactive
+ (list (let* ((std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ bookmark-default-file
+ std-default)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "File to save bookmarks in: "
+ (or (and default (file-name-directory default)) "~/")
+ default))
+ current-prefix-arg))
+ (when (file-directory-p file) (error "`%s' is a directory, not a file" file))
+ (when (and (not (file-readable-p file))
+ (not batchp)
+ (not (y-or-n-p (format "Save to NEW, EMPTY bookmark file `%s'? " file))))
+ (error "OK - canceled"))
+ (bmkp-write-alist-bookmarks-to-file (bmkp-this-file/buffer-alist-only) file addp))
+
+;;;###autoload (autoload 'bmkp-crosshairs-highlight "bookmark+")
+(defun bmkp-crosshairs-highlight () ; Not bound
+ "Highlight point with crosshairs temporarily.
+Do not highlight if either the region is active or
+`bmkp-crosshairs-flag' is nil.
+
+You can add this to hook `bookmark-after-jump-hook'.
+You need library `crosshairs.el' to use this command."
+ (interactive)
+ (when (and bmkp-crosshairs-flag (> emacs-major-version 21)) ; No-op for Emacs 20-21.
+ (unless (condition-case nil (require 'crosshairs nil t) (error nil))
+ (error "You need library `crosshairs.el' to use this command"))
+ (unless mark-active
+ (let ((crosshairs-overlay-priority (and (boundp 'bmkp-light-priorities)
+ (1+ (apply #'max
+ (mapcar #'cdr bmkp-light-priorities))))))
+ (crosshairs-highlight)))))
+
+;;;###autoload (autoload 'bmkp-choose-navlist-from-bookmark-list "bookmark+")
+(defun bmkp-choose-navlist-from-bookmark-list (bookmark &optional alist) ; Bound to `C-x x B'
+ "Choose a bookmark-list bookmark and set the bookmark navigation list.
+The navigation-list variable, `bmkp-nav-alist', is set to the list of
+bookmarks that would be displayed by `bookmark-bmenu-list' (`C-x r l')
+for the chosen bookmark-list bookmark, sorted and filtered as
+appropriate.
+
+Instead of choosing a bookmark-list bookmark, you can choose the
+pseudo-bookmark `CURRENT *Bookmark List*'. The bookmarks used for the
+navigation list are those that would be currently shown in the
+`*Bookmark List*' (even if the list is not currently displayed).
+
+BOOKMARK is a bookmark name or a bookmark record.
+Optional arg ALIST is an alternative alist of bookmarks to use."
+ (interactive
+ (let ((bookmark-alist (cons (bmkp-current-bookmark-list-state) (bmkp-bookmark-list-alist-only))))
+ (list (bmkp-read-bookmark-for-type "bookmark-list" bookmark-alist nil nil
+ 'bmkp-bookmark-list-history "Choose ")
+ bookmark-alist)))
+ (setq alist (or alist (cons (bmkp-current-bookmark-list-state) (bmkp-bookmark-list-alist-only))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR alist)))
+ (let ((state (let ((bookmark-alist alist)) (bookmark-prop-get bookmark 'bookmark-list))))
+ (let ((bname (bmkp-bookmark-name-from-record bookmark))
+ (bmkp-sort-comparer (cdr (assq 'last-sort-comparer state)))
+ (bmkp-reverse-sort-p (cdr (assq 'last-reverse-sort-p state)))
+ (bmkp-reverse-multi-sort-p (cdr (assq 'last-reverse-multi-sort-p state)))
+ (bmkp-bmenu-omitted-bookmarks (cdr (assq 'last-bmenu-omitted-bookmarks state)))
+ (bmkp-bmenu-filter-function (cdr (assq 'last-bmenu-filter-function state)))
+ (bmkp-bmenu-filter-pattern (or (cdr (assq 'last-bmenu-filter-pattern state)) ""))
+ (bmkp-bmenu-title (cdr (assq 'last-bmenu-title state)))
+ (bookmark-bmenu-toggle-filenames (cdr (assq 'last-bmenu-toggle-filenames state))))
+ (setq bmkp-nav-alist (bmkp-sort-omit
+ (if bmkp-bmenu-filter-function
+ (funcall bmkp-bmenu-filter-function)
+ (if (string= "CURRENT *Bookmark List*" bname)
+ (or bmkp-latest-bookmark-alist bookmark-alist)
+ bookmark-alist))
+ (and (not (eq bmkp-bmenu-filter-function
+ 'bmkp-omitted-alist-only))
+ bmkp-bmenu-omitted-bookmarks))
+ bmkp-current-nav-bookmark (car bmkp-nav-alist))
+ (message "Bookmark navigation list is now %s"
+ (if (and (string= "CURRENT *Bookmark List*" bname) (not (get-buffer bmkp-bmenu-buffer)))
+ "the global bookmark list"
+ (format "`%s'" bname))))))
+
+(defun bmkp-current-bookmark-list-state ()
+ "Pseudo-bookmark for the current `*Bookmark List*' state."
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (cons "CURRENT *Bookmark List*" (bmkp-make-bookmark-list-record)))
+
+;;; This function is used in macro `bmkp-define-history-variables', so
+;;; its definition is also in `bookmark+-mac.el'.
+;;;
+(defun bmkp-types-alist ()
+ "Alist of bookmark types used by `bmkp-jump-to-type'.
+Keys are bookmark type names. Values are corresponding history variables.
+The alist is used in commands such as `bmkp-jump-to-type'."
+ (let ((entries ()))
+ (mapatoms
+ (lambda (sym)
+ (let ((name (symbol-name sym)))
+ (when (string-match "\\`bmkp-\\(.+\\)-alist-only\\'" name)
+ (push (cons (match-string 1 name)
+ (intern (format "bmkp-%s-history" (match-string 1 name))))
+ entries)))))
+ entries))
+
+;;;###autoload (autoload 'bmkp-choose-navlist-of-type "bookmark+")
+(defun bmkp-choose-navlist-of-type (type) ; Bound to `C-x x :'
+ "Set the bookmark navigation list to the bookmarks of a type you choose.
+The pseudo-type `any' sets the navigation list to all bookmarks.
+This sets variable `bmkp-nav-alist'."
+ (interactive
+ (let* ((completion-ignore-case t)
+ (icicle-unpropertize-completion-result-flag t)
+ (type (completing-read "Type: "
+ (cons '("any" . bookmark-history)
+ (bmkp-types-alist))
+ nil t nil nil "any")))
+ (list type)))
+ (setq bmkp-nav-alist (if (equal "any" type)
+ bookmark-alist
+ (funcall (intern (format "bmkp-%s-alist-only" type)))))
+ (unless bmkp-nav-alist (error "No bookmarks"))
+ (setq bmkp-current-nav-bookmark (car bmkp-nav-alist))
+ (message "Bookmark navigation list is now %s"
+ (if (equal "any" type) "all bookmarks" (format "for type `%s'" type))))
+
+(defun bmkp-autonamed-bookmark-p (bookmark &optional buffer)
+ "Return non-nil if BOOKMARK is an autonamed bookmark for BUFFER.
+If BUFFER is nil then any buffer is OK.
+BOOKMARK is a bookmark name or a bookmark record.
+BUFFER, if non-nil, is a buffer or a buffer name."
+ (unless (stringp bookmark) (setq bookmark (bmkp-bookmark-name-from-record bookmark)))
+ (when (bufferp buffer) (setq buffer (buffer-name buffer)))
+ (let ((nargs 0)
+ (start 0))
+ (save-match-data
+ (while (string-match "%\\([+ #-0]+\\)?\\([0-9]+\\)?\\([.][0-9]+\\)?[BsSdoxXefgc]"
+ bmkp-autoname-format
+ start)
+ (setq nargs (1+ nargs)
+ start (match-end 0))))
+ (bmkp-string-match-p
+ (apply #'format
+ (bmkp-format-spec bmkp-autoname-format `((?B . ,(if buffer (regexp-quote buffer) ".*"))))
+ (make-list nargs ".*"))
+ bookmark)))
+
+(defun bmkp-format-spec (format specification)
+ "Like `format-spec', but respect standard `format' %-sequences.
+%-sequences specified in SPECIFICATION are handled per `format-spec'
+Any standard `format' %-sequences not specified in SPECIFICATION are
+left as is.
+
+This is also more general than `format-spec', in that the full format
+of a %-sequence is supported: `%<flags><width><precision>character'.
+`format-spec' does not support precision>, and it supports only the
+flags `-' and `0'."
+ (with-temp-buffer
+ (insert format)
+ (goto-char (point-min))
+ (while (search-forward "%" nil t)
+ (cond ((eq (char-after) ?%) (delete-char 1)) ; Quoted percent sign.
+ ((looking-at "\\([+ #-0]+\\)?\\([0-9]+\\)?\\([.][0-9]+\\)?\\([a-zA-Z]\\)")
+ (let* ((num (match-string 2))
+ (spec (string-to-char (match-string 4)))
+ (val (assq spec specification)))
+ (if (not val)
+ ;; Ignore standard format chars that are not redefined by SPECIFICATION.
+ (unless (memq (string-to-char (match-string 4)) '(?s ?S ?d ?o ?x ?X ?e ?f ?g ?c))
+ (error "Invalid format character: `%%%c'" spec))
+ (setq val (cdr val))
+ (let ((text (format (concat "%" num "s") val))) ; Pad result to desired length.
+ (insert-and-inherit text) ; Insert first, to preserve text properties.
+ (delete-region (+ (match-beginning 0) (length text)) ; Delete specifier body.
+ (+ (match-end 0) (length text)))
+ (delete-region (1- (match-beginning 0)) ; Delete percent sign.
+ (match-beginning 0))))))
+ (t (error "Invalid format string"))))
+ (buffer-string)))
+
+(defun bmkp-autonamed-this-buffer-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is an autonamed bookmark for this buffer."
+ (unless (stringp bookmark) (setq bookmark (bmkp-bookmark-name-from-record bookmark)))
+ (bmkp-autonamed-bookmark-p bookmark (buffer-name)))
+
+(defun bmkp-autonamed-bookmark-for-buffer-p (bookmark buffer-name)
+ "Return non-nil if BOOKMARK is an autonamed bookmark for BUFFER.
+BOOKMARK is a bookmark name or a bookmark record.
+BUFFER-NAME is a string matching the buffer-name part of an autoname.
+This does not check the `buffer-name' entry of BOOKMARK. It checks
+only the buffer indicated by the bookmark name."
+ (unless (stringp bookmark) (setq bookmark (bmkp-bookmark-name-from-record bookmark)))
+ (bmkp-autonamed-bookmark-p bookmark buffer-name))
+
+(defun bmkp-update-autonamed-bookmark (bookmark)
+ "Update the name and position of the autonamed BOOKMARK at point.
+Return the updated BOOKMARK: If input was a bookmark name, then return
+ then new name, else the new (full) bookmark.
+It is a good idea to set BOOKMARK to the result of this call.
+BOOKMARK is a bookmark name or a bookmark record."
+ (let ((namep (stringp bookmark)))
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (bookmark-set-position bookmark (point))
+ ;; Autonamed bookmarks do not have regions. Update `end-position' to be the same as `position'.
+ (when (bmkp-get-end-position bookmark)
+ (bookmark-prop-set bookmark 'end-position (point)))
+ (let ((newname (funcall bmkp-autoname-bookmark-function (point))))
+ (bookmark-rename (bmkp-bookmark-name-from-record bookmark) newname 'BATCHP)
+ (bmkp-refresh/rebuild-menu-list (bmkp-bookmark-name-from-record bookmark)) ; So display new name.
+ (bmkp-maybe-save-bookmarks))
+ (if namep (bmkp-bookmark-name-from-record bookmark) bookmark))) ; Return updated bookmark or name.
+
+;;;###autoload (autoload 'bmkp-this-file/buffer-bmenu-list "bookmark+")
+(defun bmkp-this-file/buffer-bmenu-list () ; Bound to `C-x x ,'
+ "Show the bookmark list just for bookmarks for the current file/buffer.
+If visiting a file, this is `bmkp-this-file-bmenu-list'. Otherwise,
+this is `bmkp-this-buffer-bmenu-list'."
+ (interactive)
+ (if (buffer-file-name) (bmkp-this-file-bmenu-list) (bmkp-this-buffer-bmenu-list)))
+
+;;;###autoload (autoload 'bmkp-this-file-bmenu-list "bookmark+")
+(defun bmkp-this-file-bmenu-list ()
+ "Show the bookmark list just for bookmarks for the current file.
+Set `bmkp-last-specific-file' to the current file name.
+If the current buffer is not visiting a file, prompt for the file name."
+ (interactive)
+ (unless bookmark-alist (bookmark-maybe-load-default-file)) ; Just to be sure.
+ (let ((orig-last-spec-file bmkp-last-specific-file)
+ (orig-filter-fn bmkp-bmenu-filter-function)
+ (orig-title bmkp-bmenu-title)
+ (orig-latest-alist bmkp-latest-bookmark-alist))
+ (condition-case err
+ (progn
+ (setq bmkp-last-specific-file (or (buffer-file-name)
+ (let ((icicle-unpropertize-completion-result-flag t))
+ (read-file-name "File: ")))
+ bmkp-bmenu-filter-function 'bmkp-last-specific-file-alist-only
+ bmkp-bmenu-title (format "File `%s' Bookmarks" bmkp-last-specific-file))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function))
+ (bmkp-bmenu-state-file nil)) ; Prevent restoring saved state.
+ (unless bookmark-alist (error "No bookmarks for file `%s'" bmkp-last-specific-file))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (pop-to-buffer (get-buffer-create bmkp-bmenu-buffer))
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order)
+ (format "Only bookmarks for file `%s' are shown"
+ bmkp-last-specific-file)))
+ (raise-frame))
+ (error (progn (setq bmkp-last-specific-file orig-last-spec-file
+ bmkp-bmenu-filter-function orig-filter-fn
+ bmkp-bmenu-title orig-title
+ bmkp-latest-bookmark-alist orig-latest-alist)
+ (error "%s" (error-message-string err)))))))
+
+;;;###autoload (autoload 'bmkp-this-buffer-bmenu-list "bookmark+")
+(defun bmkp-this-buffer-bmenu-list ()
+ "Show the bookmark list just for bookmarks for the current buffer.
+Set `bmkp-last-specific-buffer' to the current buffer name."
+ (interactive)
+ (unless bookmark-alist (bookmark-maybe-load-default-file))
+ (let ((orig-last-spec-buf bmkp-last-specific-buffer)
+ (orig-filter-fn bmkp-bmenu-filter-function)
+ (orig-title bmkp-bmenu-title)
+ (orig-latest-alist bmkp-latest-bookmark-alist))
+ (condition-case err
+ (progn
+ (setq bmkp-last-specific-buffer (buffer-name)
+ bmkp-bmenu-filter-function 'bmkp-last-specific-buffer-alist-only
+ bmkp-bmenu-title (format "Buffer `%s' Bookmarks"
+ bmkp-last-specific-buffer))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function))
+ (bmkp-bmenu-state-file nil)) ; Prevent restoring saved state.
+ (unless bookmark-alist (error "No bookmarks for buffer `%s'"
+ bmkp-last-specific-buffer))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (pop-to-buffer (get-buffer-create bmkp-bmenu-buffer))
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order)
+ (format "Only bookmarks for buffer `%s' are shown"
+ bmkp-last-specific-buffer)))
+ (raise-frame))
+ (error (progn (setq bmkp-last-specific-buffer orig-last-spec-buf
+ bmkp-bmenu-filter-function orig-filter-fn
+ bmkp-bmenu-title orig-title
+ bmkp-latest-bookmark-alist orig-latest-alist)
+ (error "%s" (error-message-string err)))))))
+
+;;;###autoload (autoload 'bmkp-navlist-bmenu-list "bookmark+")
+(defun bmkp-navlist-bmenu-list () ; Bound to `C-x x N'
+ "Show the bookmark list just for bookmarks from the navigation list."
+ (interactive)
+ (unless bmkp-nav-alist
+ (bookmark-maybe-load-default-file)
+ (setq bmkp-nav-alist bookmark-alist)
+ (unless bmkp-nav-alist (error "No bookmarks"))
+ (setq bmkp-current-nav-bookmark (car bmkp-nav-alist))
+ (message "Bookmark navigation list is now the GLOBAL bookmark list") (sit-for 2))
+ (let ((orig-title bmkp-bmenu-title)
+ (orig-latest-alist bmkp-latest-bookmark-alist))
+ (condition-case err
+ (progn
+ (setq bmkp-bmenu-title "Current Navlist Bookmarks")
+ (let ((bookmark-alist bmkp-nav-alist)
+ (bmkp-bmenu-state-file nil)) ; Prevent restoring saved state.
+ (unless bookmark-alist (error "No bookmarks"))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (pop-to-buffer (get-buffer-create bmkp-bmenu-buffer))
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order)
+ "Only bookmarks for the navigation list are shown"))
+ (raise-frame))
+ (error (progn (setq bmkp-bmenu-title orig-title
+ bmkp-latest-bookmark-alist orig-latest-alist)
+ (error "%s" (error-message-string err)))))))
+
+(defun bmkp-completing-read-buffer-name (&optional no-default-p)
+ "Read the name of a buffer associated with a bookmark.
+The candidates are the buffers in `bmkp-buffer-names'.
+Non-nil NO-DEFAULT-P means provide no default value. Used when
+ called in a loop, to let the user exit using empty input.
+If NO-DEFAULT-P is nil, then the default is the current buffer's name,
+ or the value of `bmkp-last-specific-buffer' if the current buffer has
+ no bookmarks."
+ (bookmark-maybe-load-default-file)
+ (let ((icicle-unpropertize-completion-result-flag t))
+ (completing-read "Buffer: " (mapcar #'list (bmkp-buffer-names)) nil t nil 'buffer-name-history
+ (and (not no-default-p)
+ (if (member (buffer-name) (bmkp-buffer-names))
+ (buffer-name)
+ bmkp-last-specific-buffer)))))
+
+(defun bmkp-completing-read-file-name (&optional no-default-p)
+ "Read the name of a file associated with a bookmark.
+The candidates are the absolute file names in `bmkp-file-names'.
+Non-nil NO-DEFAULT-P means provide no default value. Used when
+ called in a loop, to let the user exit using empty input.
+If NO-DEFAULT-P is nil, then the default is the current buffer's file
+ name, if any, or the value of `bmkp-last-specific-file' if the
+ current buffer has no associated file or the file has no bookmarks."
+ (bookmark-maybe-load-default-file)
+ (let ((completion-ignore-case (if (boundp 'read-file-name-completion-ignore-case)
+ read-file-name-completion-ignore-case
+ (memq system-type
+ '(ms-dos windows-nt darwin cygwin))))
+ (icicle-unpropertize-completion-result-flag t))
+ (completing-read "File: " (mapcar #'list (bmkp-file-names)) nil t nil 'file-name-history
+ (and (not no-default-p)
+ (let ((file (buffer-file-name)))
+ (if (and file (member file (bmkp-file-names)))
+ file
+ bmkp-last-specific-file))))))
+
+(defun bmkp-refresh/rebuild-menu-list (&optional bookmark no-msg-p)
+ "Refresh or rebuild buffer `*Bookmark List*'.
+If the buffer is already displayed, call `bmkp-refresh-menu-list'.
+Otherwise, call `bookmark-bmenu-surreptitiously-rebuild-list'.
+Args are the same as for `bmkp-refresh-menu-list'."
+ (let ((bmklistbuf (get-buffer bmkp-bmenu-buffer)))
+ (if (and bmklistbuf (get-buffer-window bmklistbuf 0))
+ (with-current-buffer bmklistbuf (bmkp-refresh-menu-list bookmark no-msg-p))
+ (bookmark-bmenu-surreptitiously-rebuild-list no-msg-p))))
+
+(defun bmkp-refresh-menu-list (&optional bookmark no-msg-p)
+ "Refresh (revert) the bookmark list (\"menu list\").
+This brings the displayed list up to date. It does not change the
+current filtering or sorting of the displayed list.
+Non-nil optional arg BOOKMARK means move cursor to BOOKMARK's line.
+BOOKMARK is a bookmark name or a bookmark record.
+Non-nil optional arg NO-MSG-P means do not show progress messages."
+ (let ((bookmark-alist (if bmkp-bmenu-filter-function
+ (funcall bmkp-bmenu-filter-function)
+ bookmark-alist)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (unless no-msg-p (message "Updating bookmark list..."))
+ (bookmark-bmenu-list bmkp-bmenu-filter-function) ; No filter function means start anew.
+ (when bookmark
+ (unless (stringp bookmark) (setq bookmark (bmkp-bookmark-name-from-record bookmark)))
+ (with-current-buffer (get-buffer bmkp-bmenu-buffer)
+ (bmkp-bmenu-goto-bookmark-named bookmark)
+ (let ((bmenu-win (get-buffer-window (current-buffer) 0)))
+ (when bmenu-win (set-window-point bmenu-win (point))))))
+ (unless no-msg-p (message "Updating bookmark list...done"))))
+
+;;;###autoload (autoload 'bmkp-unomit-all "bookmark+")
+(defun bmkp-unomit-all (&optional msg-p) ; Bound to `O U' in bookmark list
+ "Remove all bookmarks from the list of omitted bookmarks.
+After this, all bookmarks are available for display.
+Non-interactively, non-nil optional arg MSG-P means display a status
+message."
+ (interactive "p")
+ (unless bmkp-bmenu-omitted-bookmarks (error "No omitted bookmarks to UN-omit"))
+ (when msg-p (message "UN-omitting ALL omitted bookmarks..."))
+ (let ((count 0))
+ (dolist (bmk-name bmkp-bmenu-omitted-bookmarks)
+ (setq bmkp-bmenu-omitted-bookmarks (bmkp-delete-bookmark-name-from-list
+ bmk-name bmkp-bmenu-omitted-bookmarks)
+ count (1+ count)))
+ (bookmark-bmenu-surreptitiously-rebuild-list (not msg-p))
+ (when msg-p (message "UN-omitted %d bookmarks" count)))
+ (when (equal (buffer-name (current-buffer)) bmkp-bmenu-buffer) (bmkp-bmenu-show-all))
+ (when (and (fboundp 'fit-frame-if-one-window) (equal (buffer-name (current-buffer)) bmkp-bmenu-buffer))
+ (fit-frame-if-one-window)))
+
+
+;;(@* "Search-and-Replace Locations of Marked Bookmarks")
+;; *** Search-and-Replace Locations of Marked Bookmarks ***
+
+(when (> emacs-major-version 22)
+ (defvar bmkp-isearch-bookmarks nil
+ "Bookmarks whose locations are to be incrementally searched.")
+
+ (defun bmkp-isearch-next-bookmark-buffer (&optional bookmark wrap)
+ "Return the next buffer in a series of bookmark buffers.
+Used as a value for `multi-isearch-next-buffer-function', for Isearch
+of multiple bookmarks.
+
+Variable `bmkp-isearch-bookmarks' is a list of bookmarks. Each
+bookmark in the list is visited by `bookmark--jump-via', and the
+corresponding bookmark buffer is returned."
+ (let ((bookmarks (if isearch-forward bmkp-isearch-bookmarks (reverse bmkp-isearch-bookmarks))))
+ (bookmark--jump-via
+ (if wrap
+ (car bookmarks)
+ (let ((this-bmk (catch 'bmkp-isearch-next-bookmark-buffer
+ (dolist (bmk bookmarks)
+ (when (if (bmkp-get-buffer-name bmk)
+ (equal (bmkp-get-buffer-name bmk) (buffer-name))
+ (equal (bookmark-get-filename bmk) (buffer-file-name)))
+ (throw 'bmkp-isearch-next-bookmark-buffer bmk)))
+ (car bookmarks))))
+ (cadr (member this-bmk bookmarks))))
+ 'ignore)
+ (current-buffer)))
+
+ (defun bmkp-isearch-bookmarks (bookmarks)
+ "Start multi-bookmark Isearch on BOOKMARKS."
+ (let ((multi-isearch-next-buffer-function 'bmkp-isearch-next-bookmark-buffer)
+ (bmkp-isearch-bookmarks bookmarks))
+ (bookmark-jump (car bookmarks))
+ (goto-char (if isearch-forward (point-min) (point-max)))
+ (isearch-forward)))
+
+ (defun bmkp-isearch-bookmarks-regexp (bookmarks)
+ "Start multi-bookmark regexp Isearch on BOOKMARKS."
+ (let ((multi-isearch-next-buffer-function 'bmkp-isearch-next-bookmark-buffer)
+ (bmkp-isearch-bookmarks bookmarks))
+ (bookmark-jump (car bookmarks))
+ (goto-char (if isearch-forward (point-min) (point-max)))
+ (isearch-forward-regexp))))
+
+
+;;(@* "Tags")
+;; *** Tags ***
+
+(defun bmkp-get-tags (bookmark)
+ "Return the `tags' entry for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+ (bookmark-prop-get bookmark 'tags))
+
+(defalias 'bmkp-tagged-bookmark-p 'bmkp-get-tags)
+
+(defun bmkp-get-tag-value (bookmark tag)
+ "Return value of BOOKMARK's tag TAG.
+BOOKMARK is a bookmark name or a bookmark record.
+TAG is a string.
+Return nil if BOOKMARK has no such TAG or if TAG has no value."
+ (assoc-default tag (bmkp-get-tags bookmark)))
+
+(defun bmkp-has-tag-p (bookmark tag)
+ "Return non-nil if BOOKMARK is tagged with TAG.
+BOOKMARK is a bookmark name or a bookmark record.
+TAG is a string."
+ (assoc-default tag (bmkp-get-tags bookmark) nil t))
+
+;; NOT USED currently - we use `bmkp-read-tags-completing' instead.
+(defun bmkp-read-tags ()
+ "Read tags one by one, and return them as a list."
+ (let ((tag (read-string "Tag (RET for each, empty input to finish): "))
+ (btags ()))
+ (while (not (string= "" tag))
+ (push tag btags)
+ (setq tag (read-string "Tag: ")))
+ btags))
+
+(defun bmkp-read-tag-completing (&optional prompt candidate-tags require-match update-tags-alist-p)
+ "Read a tag with completion, and return it as a string.
+The candidate tags available are determined by option
+`bmkp-tags-for-completion'.
+
+PROMPT is the prompt string. If nil, then use \"Tag: \".
+CANDIDATE-TAGS is an alist of tags to use for completion.
+ If nil, then all tags from all bookmarks are used for completion.
+ The set of all tags is taken from variable `bmkp-tags-alist'.
+REQUIRE-MATCH is passed to `completing-read'.
+Non-nil UPDATE-TAGS-ALIST-P means update var `bmkp-tags-alist'."
+ (bookmark-maybe-load-default-file)
+ (let ((cand-tags (copy-sequence
+ (or candidate-tags
+ (and (not update-tags-alist-p)
+ bmkp-tags-alist) ; Use cached list.
+ (bmkp-tags-list)))) ; Update the cache.
+ (icicle-unpropertize-completion-result-flag t))
+ (completing-read (or prompt "Tag: ") cand-tags nil require-match nil 'bmkp-tag-history)))
+
+(defun bmkp-read-tags-completing (&optional candidate-tags require-match update-tags-alist-p)
+ "Read tags with completion, and return them as a list of strings.
+Read tags one by one, until you hit `RET' twice consecutively.
+
+CANDIDATE-TAGS is an alist of tags to use for completion.
+ If nil then the candidate tags are taken from variable
+ `bmkp-tags-alist'.
+REQUIRE-MATCH is passed to `completing-read'.
+Non-nil UPDATE-TAGS-ALIST-P means update var `bmkp-tags-alist',
+determining the tags to use per option `bmkp-tags-for-completion'."
+ (bookmark-maybe-load-default-file)
+ (let ((cands ())
+ (btags ())
+ (prompt1 "Tag (RET for each, empty input to finish): ")
+ (prompt2 "Tag: ")
+ (icicle-unpropertize-completion-result-flag t)
+ tag old-tag)
+ ;; Make a new candidates alist, with just one entry per tag name. The original cdr is discarded.
+ (dolist (full-tag (or candidate-tags
+ (and (not update-tags-alist-p) bmkp-tags-alist) ; Use cached list.
+ (bmkp-tags-list)))
+ (add-to-list 'cands (list (if (consp full-tag) (car full-tag) full-tag))))
+ (setq tag (completing-read prompt1 cands nil require-match nil 'bmkp-tag-history)
+ cands (delete (assoc tag cands) cands)) ; Tag read is no longer a candidate.
+ (while (not (string= "" tag))
+ (if (member tag btags) ; User can enter it more than once, if not REQUIRE-MATCH.
+ (message "Tag `%s' already included" tag)
+ (push tag btags)) ; But we only add it once.
+ (setq tag (completing-read prompt2 cands nil require-match nil 'bmkp-tag-history)
+ cands (delete (assoc tag cands) cands)))
+ (nreverse btags)))
+
+;;;###autoload (autoload 'bmkp-list-all-tags "bookmark+")
+(defun bmkp-list-all-tags (fullp current-only-p &optional msg-p)
+ ; Bound to `C-x x t l', (`T l' in bookmark list)
+ "List bookmark tags.
+Show the list in the minibuffer or, if not enough space, in buffer
+`*All Tags*'. The tags are listed alphabetically, respecting option
+`case-fold-search'.
+
+With no prefix arg or with a plain prefix arg (`C-u'), the tags listed
+are those defined by option `bmkp-tags-for-completion'. Otherwise
+\(i.e., with a numeric prefix arg), the tags listed are those from the
+current list of bookmarks only.
+
+With no prefix arg or with a negative prefix arg (e.g. `C--'), list
+only the tag names. With a non-negative prefix arg (e.g. `C-1' or
+plain `C-u'), list the full alist of tags.
+
+Note that when the full tags alist is shown, the same tag name appears
+once for each of its different values.
+
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive (list (and current-prefix-arg (> (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (not (consp current-prefix-arg)))
+ 'MSG))
+ (require 'pp)
+ (when msg-p (message "Gathering tags..."))
+ (pp-display-expression (sort (bmkp-tags-list (not fullp) current-only-p)
+ (if fullp
+ (lambda (t1 t2) (bmkp-string-less-case-fold-p (car t1) (car t2)))
+ 'bmkp-string-less-case-fold-p))
+ "*All Tags*"))
+
+(defun bmkp-tags-list (&optional names-only-p current-only-p)
+ "List of all bookmark tags, per option `bmkp-tags-for-completion'.
+Non-nil NAMES-ONLY-P means return a list of only the tag names.
+Otherwise, return an alist of the full tags and set variable
+`bmkp-tags-alist' to that alist, as a cache.
+
+Non-nil CURRENT-ONLY-P means ignore option `bmkp-tags-for-completion'
+and return only the tags for the currently loaded bookmarks."
+ (let ((tags ())
+ (opt-tags bmkp-tags-for-completion)
+ bmk-tags)
+ (when (or (eq opt-tags 'current) current-only-p) (setq opt-tags '(current)))
+ (dolist (entry opt-tags)
+ (typecase entry
+ (cons ; A bookmark file
+ (when (eq 'bmkfile (car entry))
+ (setq entry (cdr entry)
+ tags (append tags (bmkp-tags-in-bookmark-file entry names-only-p)))))
+ (string (add-to-list 'tags (if names-only-p entry (list entry))))
+ (symbol (when (eq entry 'current)
+ (bookmark-maybe-load-default-file)
+ (dolist (bmk bookmark-alist)
+ (setq bmk-tags (bmkp-get-tags bmk))
+ (dolist (tag bmk-tags)
+ (add-to-list 'tags (if names-only-p (bmkp-tag-name tag) (bmkp-full-tag tag)))))))))
+ (unless names-only-p (setq bmkp-tags-alist tags))
+ tags))
+
+(defun bmkp-tags-in-bookmark-file (file &optional names-only-p)
+ "Return the list of tags from all bookmarks in bookmark-file FILE.
+If FILE is a relative file name, it is expanded in `default-directory.
+If FILE does not name a valid, bookmark file then nil is returned.
+Non-nil NAMES-ONLY-P means return a list of only the tag names.
+Otherwise, return an alist of the full tags."
+ (setq file (expand-file-name file))
+ (when (file-directory-p file) (error "`%s' is a directory, not a file" file))
+ (let ((bookmark-save-flag nil) ; Just to play safe.
+ (bmk-alist ())
+ (tags ())
+ bmk-tags)
+ (if (not (file-readable-p file))
+ (message "Cannot read bookmark file `%s'" file)
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
+ (goto-char (point-min))
+ (condition-case nil ; Check whether it's a valid bookmark file.
+ (progn (bookmark-maybe-upgrade-file-format)
+ (unless (listp (setq bmk-alist (bookmark-alist-from-buffer))) (error "")))
+ (error (message "Not a valid bookmark file: `%s'" file))))
+ (dolist (bmk bmk-alist)
+ (setq bmk-tags (bmkp-get-tags bmk))
+ (dolist (tag bmk-tags)
+ (add-to-list 'tags (if names-only-p (bmkp-tag-name tag) (bmkp-full-tag tag))))))
+ tags))
+
+(defun bmkp-tag-name (tag)
+ "Name of TAG. If TAG is an atom, then TAG, else (car TAG)."
+ (if (atom tag) tag (car tag)))
+
+(defun bmkp-full-tag (tag)
+ "Full cons entry for TAG. If TAG is a cons, then TAG, else (list TAG)."
+ (if (consp tag) tag (list tag)))
+
+;;;###autoload (autoload 'bmkp-remove-all-tags "bookmark+")
+(defun bmkp-remove-all-tags (bookmark &optional no-update-p msg-p)
+ ; Bound to `C-x x t 0', (`T 0' in bookmark list)
+ "Remove all tags from BOOKMARK.
+Non-interactively:
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist', do not
+ update the modification count and maybe save bookmarks, and do not
+ refresh/rebuild the bookmark-list display
+ - Non-nil optional arg MSG-P means show a message about the removal."
+ (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) nil 'MSG))
+ (when (and msg-p (null (bmkp-get-tags bookmark))) (error "Bookmark has no tags to remove"))
+ (let ((nb-removed (and (interactive-p) (length (bmkp-get-tags bookmark)))))
+ (bookmark-prop-set bookmark 'tags ())
+ (unless no-update-p
+ (bmkp-tags-list) ; Update the tags cache.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh/rebuild-menu-list bookmark (not msg-p))) ; So remove `t' marker and add `*' marker.
+ (when (and msg-p nb-removed) (message "%d tags removed" nb-removed)))) ; Do after msg from refreshing.
+
+
+;;;###autoload (autoload 'bmkp-add-tags "bookmark+")
+(defun bmkp-add-tags (bookmark tags &optional no-update-p msg-p)
+ ; `C-x x t + b' (`b' for bookmark), (`T +' in bookmark list)
+ "Add TAGS to BOOKMARK.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+Completion for the bookmark name is strict.
+Completion for tags is lax: you are not limited to existing tags.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them.
+
+Non-interactively:
+ - TAGS is a list of strings.
+ - Non-nil MSG-P means display a message about the addition.
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist', do not
+ update the modification count and maybe save bookmarks, and do not
+ refresh/rebuild the bookmark-list display
+
+The absolute value of the return value is the number of tags added.
+If BOOKMARK was untagged before the operation, then the return value
+is negative."
+ (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name))
+ (bmkp-read-tags-completing nil nil current-prefix-arg)
+ nil
+ 'MSG))
+ (let* ((newtags (copy-alist (bmkp-get-tags bookmark)))
+ (olen (length newtags)))
+ (dolist (tag tags) (unless (or (assoc tag newtags) (member tag newtags)) (push tag newtags)))
+ (bookmark-prop-set bookmark 'tags newtags)
+ (unless no-update-p
+ (bmkp-tags-list) ; Update the tags cache.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh/rebuild-menu-list bookmark (not msg-p))) ; So display `t' and `*' markers for BOOKMARK.
+ (let ((nb-added (- (length newtags) olen)))
+ (when msg-p (message "%d tags added. Now: %S" nb-added ; Echo just the tag names.
+ (let ((tgs (mapcar #'bmkp-tag-name newtags))) (setq tgs (sort tgs #'string<)))))
+ (when (and (zerop olen) (> (length newtags) 0)) (setq nb-added (- nb-added)))
+ nb-added)))
+
+;; $$$$$$ Not yet used
+;;;###autoload (autoload 'bmkp-set-tag-value-for-navlist "bookmark+")
+(defun bmkp-set-tag-value-for-navlist (tag value &optional msg-p) ; Bound to `C-x x t V'
+ "Set the value of TAG to VALUE, for each bookmark in the navlist.
+If any of the bookmarks has no tag named TAG, then add one with VALUE."
+ (interactive (list (bmkp-read-tag-completing) (read (read-string "Value: ")) 'msg))
+ (bmkp-set-tag-value-for-bookmarks bmkp-nav-alist tag value msg-p))
+
+;; $$$$$$ Not yet used
+(defun bmkp-set-tag-value-for-bookmarks (bookmarks tag value &optional msg-p) ; Not bound
+ "Set the value of TAG to VALUE, for each of the BOOKMARKS.
+If any of the BOOKMARKS has no tag named TAG, then add one with VALUE."
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save only after `dolist'.
+ (dolist (bmk bookmarks) (bmkp-set-tag-value bmk tag value 'NO-UPDATE-P)))
+ (bmkp-tags-list) ; Update the tags cache.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh/rebuild-menu-list nil (not msg-p)))
+
+;;;###autoload (autoload 'bmkp-set-tag-value "bookmark+")
+(defun bmkp-set-tag-value (bookmark tag value &optional no-update-p msg-p) ; Bound to `C-x x t v'
+ "For BOOKMARK's TAG, set the value to VALUE.
+If BOOKMARK has no tag named TAG, then add one with value VALUE.
+Non-interactively:
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist', do not
+ update the modification count and maybe save bookmarks, and do not
+ refresh/rebuild the bookmark-list display
+ - Non-nil MSG-P means display a message about the updated value."
+ (interactive
+ (let* ((bmk (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)))
+ (tag (bmkp-read-tag-completing "Tag: " (mapcar 'bmkp-full-tag (bmkp-get-tags bmk)))))
+ (list bmk tag (read (read-string "Value: ")) nil 'MSG)))
+ (unless (bmkp-has-tag-p bookmark tag) (bmkp-add-tags bookmark (list tag) 'NO-UPDATE-P)) ; No update yet.
+ (let* ((newtags (copy-alist (bmkp-get-tags bookmark)))
+ (assoc-tag (assoc tag newtags))
+ (member-tag (and (not assoc-tag) (member tag newtags))))
+ (if assoc-tag (setcdr assoc-tag value) (setcar member-tag (cons (car member-tag) value)))
+ (bookmark-prop-set bookmark 'tags newtags))
+ (unless no-update-p
+ (bmkp-tags-list) ; Update the tags cache.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh/rebuild-menu-list bookmark (not msg-p))) ; So display `t' and `*' markers for BOOKMARK.
+ (when msg-p "Tag value set"))
+
+;;;###autoload (autoload 'bmkp-remove-tags "bookmark+")
+(defun bmkp-remove-tags (bookmark tags &optional no-update-p msg-p)
+ ; `C-x x t - b' (`b' for bookmark), (`T -' in bookmark list)
+ "Remove TAGS from BOOKMARK.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them.
+
+Non-interactively:
+ - TAGS is a list of strings. The corresponding tags are removed.
+ - Non-nil MSG-P means display status messages.
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist', do not
+ update the modification count and maybe save bookmarks, and do not
+ refresh/rebuild the bookmark-list display
+
+The absolute value of the return value is the number of tags removed.
+If BOOKMARK is untagged after the operation, then the return value
+is negative."
+ (interactive (let ((bmk (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name))))
+ (list bmk
+ (bmkp-read-tags-completing (mapcar 'bmkp-full-tag (bmkp-get-tags bmk))
+ t current-prefix-arg)
+ nil
+ 'MSG)))
+ (let* ((remtags (copy-alist (bmkp-get-tags bookmark)))
+ (olen (length remtags)))
+ (if (null remtags)
+ (when msg-p (message "Bookmark has no tags to remove")) ; Do nothing if bookmark has no tags.
+ (setq remtags (bmkp-remove-if (lexical-let ((tgs tags))
+ (lambda (tag)
+ (if (atom tag) (member tag tgs) (member (car tag) tgs))))
+ remtags))
+ (bookmark-prop-set bookmark 'tags remtags)
+ (unless no-update-p
+ (bmkp-tags-list) ; Update the tags cache.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh/rebuild-menu-list bookmark (not msg-p))) ; So remove `t' marker if no tags.
+ (let ((nb-removed (- olen (length remtags))))
+ (when msg-p (message "%d tags removed. Now: %S" nb-removed ; Echo just the tag names.
+ (let ((tgs (mapcar #'bmkp-tag-name remtags)))
+ (setq tgs (sort tgs #'string<)))))
+ (when (and (zerop (length remtags)) (> olen 0)) (setq nb-removed (- nb-removed)))
+ nb-removed))))
+
+;;;###autoload (autoload 'bmkp-remove-tags-from-all "bookmark+")
+(defun bmkp-remove-tags-from-all (tags &optional msg-p) ; Bound to `C-x x t d', (`T d' in bookmark list)
+ "Remove TAGS from all bookmarks.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter each tag.
+This affects all bookmarks, even those not showing in bookmark list.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them.
+
+Non-interactively:
+* TAGS is a list of strings. The corresponding tags are removed.
+* Non-nil optional arg MSG-P means show a message about the deletion."
+ (interactive
+ (if (not (y-or-n-p "Delete the tags you specify from ALL bookmarks? "))
+ (error "OK - deletion canceled")
+ (list (bmkp-read-tags-completing nil t current-prefix-arg) 'MSG)))
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save only after `dolist'.
+ (dolist (bmk (bookmark-all-names)) (bmkp-remove-tags bmk tags 'NO-UPDATE-P)))
+ (bmkp-tags-list) ; Update the tags cache (only once, at end).
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh/rebuild-menu-list nil (not msg-p)) ; So remove `t' markers when no tags anymore.
+ (when msg-p (message "Tags removed from all bookmarks: %S" tags)))
+
+;;;###autoload (autoload 'bmkp-rename-tag "bookmark+")
+(defun bmkp-rename-tag (tag newname &optional msg-p) ; Bound to `C-x x t r', (`T r' in bookmark list)
+ "Rename TAG to NEWNAME in all bookmarks, even those not showing.
+Non-interactively, non-nil MSG-P means display a message about the
+deletion."
+ (interactive (list (bmkp-read-tag-completing "Tag (old name): ")
+ (bmkp-read-tag-completing "New name: ")
+ 'MSG))
+ (let ((tag-exists-p nil)
+ (bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save only after `dolist'.
+ (dolist (bmk (bookmark-all-names))
+ (let ((newtags (copy-alist (bmkp-get-tags bmk))))
+ (when newtags
+ (let* ((assoc-tag (assoc tag newtags))
+ (member-tag (and (not assoc-tag) (member tag newtags))))
+ (cond (assoc-tag (setcar assoc-tag newname))
+ (member-tag (setcar member-tag newname)))
+ (when (or assoc-tag member-tag)
+ (setq tag-exists-p t)
+ (bookmark-prop-set bmk 'tags newtags))))))
+ (unless tag-exists-p (error "No such tag: `%s'" tag)))
+ (bmkp-tags-list) ; Update the tags cache now, after iterating.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ ;; (bmkp-refresh/rebuild-menu-list nil (not msg-p)) ; $$$$$$ No need to redisplay
+ (when msg-p (message "Renamed")))
+
+;;;###autoload (autoload 'bmkp-copy-tags "bookmark+")
+(defun bmkp-copy-tags (bookmark &optional msg-p) ; Bound to `C-x x t c', `C-x x t M-w'
+ "Copy tags from BOOKMARK, so you can paste them to another bookmark.
+Note that you can copy from a BOOKMARK that has no tags or has an
+empty tags list. In that case, the copied-tags list is empty, so if
+you paste it as a replacement then the recipient bookmark will end up
+with no tags.
+
+Non-interactively, non-nil MSG-P means display a message about the
+number of tags copied."
+ (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) 'MSG))
+ (let ((btags (bmkp-get-tags bookmark)))
+ (setq bmkp-copied-tags (copy-alist btags))
+ (when msg-p (message "%d tags now available for pasting" (length btags)))))
+
+;;;###autoload (autoload 'bmkp-paste-add-tags "bookmark+")
+(defun bmkp-paste-add-tags (bookmark &optional no-update-p msg-p) ; Bound to `C-x x t p', `C-x x t C-y'
+ "Add tags to BOOKMARK that were previously copied from another bookmark.
+Return the number of tags added.
+The tags are copied from `bmkp-copied-tags'.
+Non-interactively:
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist', do not
+ update the modification count and maybe save bookmarks, and do not
+ refresh/rebuild the bookmark-list display
+ - Non-nil MSG-P means display a message about the addition."
+ (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) nil 'MSG))
+ (unless (listp bmkp-copied-tags) (error "`bmkp-paste-add-tags': `bmkp-copied-tags' is not a list"))
+ (bmkp-add-tags bookmark bmkp-copied-tags no-update-p msg-p))
+
+;;;###autoload (autoload 'bmkp-paste-replace-tags "bookmark+")
+(defun bmkp-paste-replace-tags (bookmark &optional no-update-p msg-p) ; Bound to `C-x x t q'
+ "Replace tags for BOOKMARK with those copied from another bookmark.
+Return the number of tags for BOOKMARK.
+The tags are copied from `bmkp-copied-tags'.
+Any previously existing tags for BOOKMARK are *lost*.
+
+NOTE: It is by design that you can *remove all* tags from a bookmark
+by copying an empty set of tags and then pasting to that bookmark
+using this command. So be careful using it. If you want to be sure
+that you do not replace tags with an empty list of tags, you can check
+the value of variable `bmkp-copied-tags' before pasting.
+
+Non-interactively:
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist', do not
+ update the modification count and maybe save bookmarks, and do not
+ refresh/rebuild the bookmark-list display
+ - Non-nil MSG-P means display a message about the addition."
+ (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) nil 'MSG))
+ (unless (listp bmkp-copied-tags)
+ (error "`bmkp-paste-replace-tags': `bmkp-copied-tags' is not a list"))
+ (let ((has-tags-p (bmkp-get-tags bookmark)))
+ (when (and msg-p has-tags-p
+ (not (y-or-n-p "Existing tags will be LOST - really replace them? ")))
+ (error "OK - paste-replace tags canceled"))
+ (when has-tags-p (bmkp-remove-all-tags bookmark no-update-p msg-p) (sleep-for 0.5)))
+ (bmkp-add-tags bookmark bmkp-copied-tags no-update-p msg-p))
+
+
+;;(@* "Bookmark Predicates")
+;; *** Bookmark Predicates ***
+
+(defun bmkp-annotated-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK has an annotation.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (let ((annotation (bookmark-get-annotation bookmark)))
+ (and annotation (not (string-equal annotation "")))))
+
+(defun bmkp-autofile-bookmark-p (bookmark &optional prefix)
+ "Return non-nil if BOOKMARK is an autofile bookmark.
+That means both:
+ * It is `bmkp-file-bookmark-p'.
+ * Its bookmark name is the same as the nondirectory part of its file
+ name (or of its `directory-file-name', if a directory).
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'.
+
+Non-interactively, non-nil optional arg PREFIX means that the bookmark
+name is actually expected to be the file name prefixed by PREFIX (a
+string)."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (and (bmkp-file-bookmark-p bookmark)
+ (let* ((file (bookmark-get-filename bookmark))
+ (fname (file-name-nondirectory (if (file-directory-p file)
+ (directory-file-name file)
+ file))))
+ (string= (if prefix (concat prefix fname) fname) (bmkp-bookmark-name-from-record bookmark)))))
+
+(defun bmkp-bookmark-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a bookmark-file bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-bookmark-file))
+
+(defun bmkp-bookmark-list-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a bookmark-list bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-bookmark-list))
+
+(defun bmkp-desktop-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a desktop bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-desktop))
+
+;; Note: To avoid remote access, if bookmark does not have the Dired handler, then we insist
+;; that it be for a local directory. IOW, we do not include remote directories that were not
+;; bookmarked by Bookmark+ (and so do not have the Dired handler).
+(defun bmkp-dired-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a Dired bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (or (eq (bookmark-get-handler bookmark) 'bmkp-jump-dired)
+ (bmkp-local-directory-bookmark-p bookmark)))
+
+(defun bmkp-dired-this-dir-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a Dired bookmark for the `default-directory'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (and (bmkp-dired-bookmark-p bookmark)
+ (let ((dir (file-name-directory (bookmark-get-filename bookmark))))
+ (bmkp-same-file-p dir default-directory))))
+
+(defun bmkp-dired-wildcards-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a Dired buffer with wildcards.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (and (bmkp-dired-bookmark-p bookmark)
+ (let ((file (bookmark-get-filename bookmark)))
+ (and (stringp file) (bmkp-string-match-p (regexp-quote "*") file)))))
+
+(when (> emacs-major-version 24) ; Emacs 25+
+
+ (defun bmkp-eww-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is an EWW bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-eww))
+
+ )
+
+(defun bmkp-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a file or directory.
+This excludes bookmarks of a more specific kind (e.g. Info, Gnus).
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let* ((filename (bookmark-get-filename bookmark))
+ (nonfile-p (equal filename bmkp-non-file-filename))
+ (handler (bookmark-get-handler bookmark)))
+ (and filename (not nonfile-p)
+ (or (not handler)
+ (memq handler bmkp-file-bookmark-handlers)
+ (equal handler (bmkp-default-handler-for-file filename)))
+ (not (bookmark-prop-get bookmark 'info-node))))) ; Emacs 20-21 Info: no handler.
+
+(defun bmkp-file-this-dir-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks file/subdir in `default-directory'.
+This excludes bookmarks of a more specific kind (e.g. Info, Gnus).
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark 'NOERROR))
+ (and bookmark
+ (bmkp-file-bookmark-p bookmark)
+ (bmkp-same-file-p (file-name-directory (bookmark-get-filename bookmark)) default-directory)))
+
+(defun bmkp-flagged-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is flagged for deletion in `*Bookmark List*'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (memq bookmark bmkp-flagged-bookmarks))
+
+(defun bmkp-function-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a function bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-function))
+
+(defun bmkp-gnus-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a Gnus bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (memq (bookmark-get-handler bookmark)
+ '(gnus-summary-bookmark-jump bmkp-jump-gnus bmkext-jump-gnus)))
+
+(defun bmkp-icicles-search-hits-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK records a list of Icicles search hits.
+BOOKMARK is a bookmark name or a bookmark record.
+
+An Icicles search-hits bookmark is shown in the bookmark-list display
+with face `bmkp-no-jump', because you cannot jump to it from there."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-icicle-search-hits))
+
+(defun bmkp-image-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is an image-file bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (or (eq (bookmark-get-handler bookmark) 'image-bookmark-jump)
+ (and (fboundp 'image-file-name-regexp) ; In `image-file.el' (Emacs 22+).
+ (bmkp-file-bookmark-p bookmark)
+ (not (bmkp-dired-bookmark-p bookmark))
+ (bmkp-string-match-p (image-file-name-regexp) (bookmark-get-filename bookmark)))))
+
+(defun bmkp-info-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is an Info bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (or (eq (bookmark-get-handler bookmark) 'Info-bookmark-jump)
+ (and (not (bookmark-get-handler bookmark))
+ (or (string= "*info*" (bmkp-get-buffer-name bookmark))
+ (bookmark-prop-get bookmark 'info-node))))) ; Emacs 20-21 - no `buffer-name' entry.
+
+(defun bmkp-kmacro-list-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a kmacro-list bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-kmacro-list))
+
+(defun bmkp-local-directory-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a local directory.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let ((file (bookmark-get-filename bookmark)))
+ (and (bmkp-local-file-bookmark-p bookmark) (file-directory-p file))))
+
+(defun bmkp-local-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a local file or directory.
+This excludes bookmarks of a more specific kind (e.g. Info, Gnus).
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (and (bmkp-file-bookmark-p bookmark) (not (bmkp-remote-file-bookmark-p bookmark))))
+
+(defun bmkp-local-non-dir-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a local nondirectory file.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let ((file (bookmark-get-filename bookmark)))
+ (and (bmkp-local-file-bookmark-p bookmark) (not (file-directory-p file)))))
+
+(defun bmkp-buffer-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a non-file buffer.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (and (bmkp-get-buffer-name bookmark)
+ (let ((filep (bookmark-get-filename bookmark)))
+ (or (not filep) (equal filep bmkp-non-file-filename)))))
+
+(defun bmkp-man-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a `man' page bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (memq (bookmark-get-handler bookmark) '(bmkp-jump-man bmkp-jump-woman
+ bmkext-jump-man bmkext-jump-woman)))
+
+(defun bmkp-marked-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a marked bookmark in `*Bookmark List*'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (unless (stringp bookmark) (setq bookmark (bmkp-bookmark-name-from-record bookmark)))
+ (bmkp-bookmark-name-member bookmark bmkp-bmenu-marked-bookmarks))
+
+(defun bmkp-modified-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a modified bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (memq bookmark bmkp-modified-bookmarks))
+
+(defun bmkp-navlist-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is in the current navigation list.
+BOOKMARK is a bookmark name or a bookmark record."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (memq bookmark bmkp-nav-alist))
+
+(defun bmkp-non-dir-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a nondirectory file.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let ((file (bookmark-get-filename bookmark)))
+ (and (bmkp-file-bookmark-p bookmark) (not (file-directory-p file)))))
+
+(defun bmkp-non-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a non-file bookmark (e.g *scratch*).
+This excludes bookmarks of a more specific kind (e.g. Info, Gnus).
+It includes bookmarks to existing buffers, as well as bookmarks
+defined for buffers that do not currently exist.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let* ((filename (bookmark-get-filename bookmark))
+ (nonfile-p (equal filename bmkp-non-file-filename)))
+ (and (bmkp-get-buffer-name bookmark)
+ (or (not filename) nonfile-p
+ ;; Ensure not remote before calling `file-exists-p'. (Do not prompt for password.)
+ (and (not (bmkp-file-remote-p filename)) (not (file-exists-p filename))))
+ (not (bookmark-get-handler bookmark)))))
+
+(defun bmkp-non-invokable-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a non-invokable bookmark.
+That is, jumping to it has no effect, because its handler is `ignore'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'.
+
+A non-invokable bookmark is shown in the bookmark-list display with
+face `bmkp-no-jump', because you cannot jump to it."
+ (eq (bookmark-get-handler bookmark) 'ignore))
+
+(defun bmkp-orphaned-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is an orphaned file or directory bookmark.
+This means that the file recorded for BOOKMARK does not exist or is
+not readable. But a Dired bookmark with wildcards in the file name is
+assumed to be readable.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (and (bmkp-file-bookmark-p bookmark)
+ (if (bmkp-dired-bookmark-p bookmark)
+ (and (not (bmkp-dired-wildcards-bookmark-p bookmark))
+ (not (file-readable-p (bookmark-get-filename bookmark))))
+ (not (file-readable-p (bookmark-get-filename bookmark))))))
+
+(defun bmkp-orphaned-local-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is an orphaned local-file bookmark.
+This means that the file name recorded for BOOKMARK is not remote, and
+the file does not exist or is not readable. But a Dired bookmark with
+wildcards in the file name is assumed to be readable.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (and (bmkp-local-file-bookmark-p bookmark)
+ (if (bmkp-dired-bookmark-p bookmark)
+ (and (not (bmkp-dired-wildcards-bookmark-p bookmark))
+ (not (file-readable-p (bookmark-get-filename bookmark))))
+ (not (file-readable-p (bookmark-get-filename bookmark))))))
+
+(defun bmkp-orphaned-remote-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is an orphaned remote-file bookmark.
+This means that the file name recorded for BOOKMARK is remote, and the
+file does not exist or is not readable. But a Dired bookmark with
+wildcards in the file name is assumed to be readable.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (and (bmkp-remote-file-bookmark-p bookmark)
+ (if (bmkp-dired-bookmark-p bookmark)
+ (and (not (bmkp-dired-wildcards-bookmark-p bookmark))
+ (not (file-readable-p (bookmark-get-filename bookmark))))
+ (not (file-readable-p (bookmark-get-filename bookmark))))))
+
+(defun bmkp-region-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK has region information.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (and (bmkp-get-end-position bookmark)
+ (bookmark-get-position bookmark)
+ (/= (bookmark-get-position bookmark) (bmkp-get-end-position bookmark))))
+
+(defun bmkp-remote-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a remote file or directory.
+This includes remote Dired bookmarks, but otherwise excludes bookmarks
+with handlers (e.g. Info, Gnus).
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let* ((handler (bookmark-get-handler bookmark))
+ (file (bookmark-get-filename bookmark))
+ (rem-file (and file (bmkp-file-remote-p file))))
+ (and rem-file (or (not handler) (eq handler 'bmkp-jump-dired)))))
+
+(defun bmkp-remote-non-dir-file-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a remote nondirectory file.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let ((file (bookmark-get-filename bookmark)))
+ (and (bmkp-remote-file-bookmark-p bookmark) (not (file-directory-p file)))))
+
+(defun bmkp-snippet-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a snippet bookmark.
+This means that it records a snippet of text and that jumping to it
+copies that text to the `kill-ring'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-snippet))
+
+(defun bmkp-temporary-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is temporary.
+This means that it has a non-nil `bmkp-temp' entry.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (setq bookmark (bmkp-get-bookmark bookmark 'NOERROR))
+ (and bookmark (bookmark-prop-get bookmark 'bmkp-temp)))
+
+(defun bmkp-this-buffer-p (bookmark)
+ "Return non-nil if BOOKMARK's buffer is the current buffer.
+But return nil if BOOKMARK has an associated file, but it is not the
+ buffer's file.
+And return nil for bookmarks, such as desktops, that are not really
+ associated with a buffer, even if they have a `buffer-name' entry.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (and (let ((this-file (condition-case nil (bookmark-buffer-file-name) (error nil)))
+ (bmk-file (and (bmkp-file-bookmark-p bookmark) (bookmark-get-filename bookmark))))
+ ;; Two possibilities:
+ ;; * Neither buffer nor bookmark has a file, and the buffer names are the same.
+ ;; * Both have files, and they are the same file.
+ (or (and (not this-file) (not bmk-file) (equal (bmkp-get-buffer-name bookmark) (buffer-name)))
+ (and this-file bmk-file (bmkp-same-file-p this-file bmk-file))))
+ ;; If the buffer to check is from EWW, the buffer URL must match the bookmark URL.
+ (or (not (eq major-mode 'eww-mode))
+ (and (fboundp 'bmkp-eww-url) (equal (bookmark-location bookmark) (bmkp-eww-url)))) ; Emacs 25+
+ (not (bmkp-desktop-bookmark-p bookmark))
+ (not (bmkp-bookmark-file-bookmark-p bookmark))
+ (not (bmkp-sequence-bookmark-p bookmark))
+ (not (bmkp-function-bookmark-p bookmark))
+ (not (bmkp-variable-list-bookmark-p bookmark))))
+
+(defun bmkp-this-file-p (bookmark)
+ "Return non-nil if BOOKMARK's file is the visited file.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let ((bmk-file (and (bmkp-file-bookmark-p bookmark) (bookmark-get-filename bookmark)))
+ (this-file (or (and (buffer-file-name) (bookmark-buffer-file-name))
+ (and (eq major-mode 'dired-mode) (if (consp dired-directory)
+ (car dired-directory)
+ dired-directory)))))
+ (and bmk-file this-file (bmkp-same-file-p this-file bmk-file))))
+
+(defun bmkp-last-specific-buffer-p (bookmark)
+ "Return t if BOOKMARK's `buffer-name' is `bmkp-last-specific-buffer'.
+But return nil for bookmarks, such as desktops, that are not really
+associated with a buffer, even if they have a `buffer-name' entry.
+It does not matter whether the buffer exists.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let ((buf (bmkp-get-buffer-name bookmark)))
+ (and buf (string= buf bmkp-last-specific-buffer)
+ (not (bmkp-desktop-bookmark-p bookmark))
+ (not (bmkp-bookmark-file-bookmark-p bookmark))
+ (not (bmkp-sequence-bookmark-p bookmark))
+ (not (bmkp-function-bookmark-p bookmark))
+ (not (bmkp-variable-list-bookmark-p bookmark)))))
+
+(defun bmkp-last-specific-file-p (bookmark)
+ "Return t if BOOKMARK's `filename' is `bmkp-last-specific-file'.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (let ((file (bookmark-get-filename bookmark)))
+ (and file (bmkp-same-file-p file bmkp-last-specific-file))))
+
+(defun bmkp-sequence-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a sequence bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-sequence))
+
+(defun bmkp-some-marked-p (alist)
+ "Return non-nil if ALIST is nonempty and includes a marked bookmark."
+ (catch 'break (dolist (i alist) (and (bmkp-marked-bookmark-p i) (throw 'break t)))))
+
+(defun bmkp-some-unmarked-p (alist)
+ "Return non-nil if ALIST is nonempty and includes an unmarked bookmark."
+ (catch 'break (dolist (i alist) (and (not (bmkp-marked-bookmark-p i)) (throw 'break t)))))
+
+(defun bmkp-url-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a URL bookmark.
+This means that it satifies `bmkp-eww-bookmark-p' (Emacs 25+),
+`bmkp-w3m-bookmark-p', or `bmkp-url-browse-bookmark-p'.
+
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (or (and (fboundp 'bmkp-eww-bookmark-p) (bmkp-eww-bookmark-p bookmark))
+ (bmkp-w3m-bookmark-p bookmark)
+ (bmkp-url-browse-bookmark-p bookmark)))
+
+(defun bmkp-url-browse-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a `browse-url' bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-url-browse))
+
+(defun bmkp-variable-list-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a variable-list bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (eq (bookmark-get-handler bookmark) 'bmkp-jump-variable-list))
+
+(defun bmkp-w3m-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a W3M bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (memq (bookmark-get-handler bookmark) '(bmkp-jump-w3m bmkext-jump-w3m)))
+
+
+
+
+
+;;(@* "General Utility Functions")
+;; *** General Utility Functions ***
+
+(when (and (fboundp 'cl-puthash) (not (fboundp 'puthash))) ; Emacs 20 with `cl-extra.el' loaded.
+ (defalias 'puthash 'cl-puthash))
+
+(if (fboundp 'puthash) ; Emacs 21+, or Emacs 20 with `cl-extra.el' loaded.
+ (defun bmkp-remove-dups (sequence &optional test)
+ "Copy of SEQUENCE with duplicate elements removed.
+Optional arg TEST is the test function. If nil, test with `equal'.
+See `make-hash-table' for possible values of TEST."
+ (setq test (or test #'equal))
+ (let ((htable (make-hash-table :test test)))
+ (loop for elt in sequence
+ unless (gethash elt htable)
+ do (puthash elt elt htable)
+ finally return (loop for i being the hash-values in htable collect i))))
+
+ (defun bmkp-remove-dups (list &optional use-eq)
+ "Copy of LIST with duplicate elements removed.
+Test using `equal' by default, or `eq' if optional USE-EQ is non-nil."
+ (let ((tail list)
+ new)
+ (while tail
+ (unless (if use-eq (memq (car tail) new) (member (car tail) new))
+ (push (car tail) new))
+ (pop tail))
+ (nreverse new))))
+
+(defun bmkp-unpropertized-string (string)
+ "Return a copy of STRING, but with properties removed.
+Does not change the original STRING."
+ (let ((strg (copy-sequence string)))
+ (set-text-properties 0 (length strg) () strg)
+ strg))
+
+;; For a name propertized with `bmkp-full-record', this is similar to `bmkp-assoc-delete-all'.
+(defun bmkp-delete-bookmark-name-from-list (delname bnames)
+ "Delete names that represent the same bookmark as DELNAME from BNAMES.
+This means that they are `string=' and they either have no property
+`bmkp-full-record' or that property has the same value.
+Return the modified list BNAMES."
+ ;; $$$$$$ Can we change `equal' to `eq' everywhere here?
+ (let ((delprop (get-text-property 0 'bmkp-full-record delname))
+ bmkprop)
+ (if (not delprop)
+ (setq bnames (delete delname bnames)) ; Unpropertized - just use `delete'.
+ ;; Propertized. Delete names that are `string=' and have the same property value or none.
+ (while (and bnames (string= delname (car bnames)) ; Delete those at list beginning.
+ (or (not (setq bmkprop (get-text-property 0 'bmkp-full-record (car bnames))))
+ (equal delprop bmkprop)))
+ (setq bnames (cdr bnames)))
+ (let ((tail bnames) ; Delete those not at list beginning.
+ tail-cdr)
+ (while (setq tail-cdr (cdr tail))
+ (if (and (car tail-cdr)
+ (string= delname (car tail-cdr))
+ (or (not (setq bmkprop (get-text-property 0 'bmkp-full-record (car tail-cdr))))
+ (equal delprop bmkprop)))
+ (setcdr tail (cdr tail-cdr))
+ (setq tail tail-cdr))))
+ bnames)))
+
+(defun bmkp-bookmark-name-member (name names)
+ "Like `member', but tests also bookmark NAME's `bmkp-full-record' property.
+Return the tail of NAMES whose car is NAME with the property match.
+If NAME has no `bmkp-full-record' property then this is just `member'.
+If NAME has property `bmkp-full-record', then test whether both:
+ a. NAME is a member of NAMES and
+ b. NAME has the same `bmkp-full-record' value as an element of NAMES."
+ ;; $$$$$$ Can we change `equal' to `eq' here?
+ (let ((prop (get-text-property 0 'bmkp-full-record name)))
+ (if (or (null name) (not prop))
+ (member name names) ; Unpropertized - just use `member'.
+ (while (and names (not (and (stringp (car names))
+ (string= name (car names)) ; = `bmkp-names-same-bookmark-p'.
+ ;; If unpropertized in NAMES, then assume it's the one.
+ (or (not (get-text-property 0 'bmkp-full-record (car names)))
+ (equal prop (get-text-property 0 'bmkp-full-record (car names)))))))
+ (setq names (cdr names)))
+ names)))
+
+(defun bmkp-names-same-bookmark-p (name1 name2)
+ "Return non-nil if the two strings name the same bookmark.
+The strings are `string=' and their `bmkp-full-record' property values
+for the first character are `equal'."
+
+ ;; $$$$$$ Can we change `equal' to `eq' here?
+ (and (string= name1 name2)
+ (equal (get-text-property 0 'bmkp-full-record name1)
+ (get-text-property 0 'bmkp-full-record name2))))
+
+(defun bmkp-read-buffers ()
+"Read names of buffers associated with bookmarks.
+Invoke `bmkp-completing-read-buffer-name' repeatedly till input is empty."
+ (let ((buffs ())
+ buff)
+ (while (and (setq buff (bmkp-completing-read-buffer-name 'ALLOW-EMPTY)) (not (string= "" buff)))
+ (add-to-list 'buffs buff))
+ buffs))
+
+(defun bmkp-read-files ()
+ "Read names of files associated with bookmarks.
+Invoke `bmkp-completing-read-file-name' repeatedly till input is empty."
+ (let ((use-file-dialog nil)
+ (files ())
+ file)
+ (while (and (setq file (bmkp-completing-read-file-name 'ALLOW-EMPTY)) (not (string= "" file)))
+ (add-to-list 'files file))
+ files))
+
+(defun bmkp-remove-if (pred xs)
+ "A copy of list XS with no elements that satisfy predicate PRED."
+ (let ((result ()))
+ (dolist (x xs) (unless (funcall pred x) (push x result)))
+ (nreverse result)))
+
+(defun bmkp-remove-if-not (pred xs)
+ "A copy of list XS with only elements that satisfy predicate PRED."
+ (let ((result ()))
+ (dolist (x xs) (when (funcall pred x) (push x result)))
+ (nreverse result)))
+
+;; Similar to `every' in `cl-extra.el', without non-list sequences and multiple sequences.
+(defun bmkp-every (predicate list)
+ "Return t if PREDICATE is true for all elements of LIST; else nil."
+ (while (and list (funcall predicate (car list))) (setq list (cdr list)))
+ (null list))
+
+;; Same as `zz-some' in `zones.el'.
+;; This is NOT the same as `some' in `cl-extra.el', even without non-list sequences and multiple sequences.
+;;
+;; If PREDICATE is satisfied by a list element ELEMENT, so that it returns a non-nil value VALUE for ELEMENT,
+;; then this returns the cons (ELEMENT . VALUE). It does not return just VALUE.
+(defun bmkp-some (predicate list)
+ "Return non-nil if PREDICATE applied to some element of LIST is true.
+The value returned is a cons, (ELEMENT . VALUE), where ELEMENT is the
+first list element that satisfies PREDICATE and VALUE is the value of
+PREDICATE applied to ELEMENT."
+ (let (elt val)
+ (catch 'bmkp-some
+ (while list
+ (when (setq val (funcall predicate (setq elt (pop list))))
+ (throw 'bmkp-some (cons elt val))))
+ nil)))
+
+;; From `cl-seq.el', function `union', without keyword treatment.
+;; (Same as `icicle-set-union' in `icicles-fn.el'.)
+(defun bmkp-set-union (list1 list2)
+ "Combine LIST1 and LIST2 using a set-union operation.
+The result list contains all items that appear in either LIST1 or
+LIST2. Comparison is done using `equal'. This is a non-destructive
+function; it copies the data if necessary."
+ (cond ((null list1) list2)
+ ((null list2) list1)
+ ((equal list1 list2) list1)
+ (t
+ (unless (>= (length list1) (length list2))
+ (setq list1 (prog1 list2 (setq list2 list1)))) ; Swap them.
+ (while list2
+ (unless (member (car list2) list1) (setq list1 (cons (car list2) list1)))
+ (setq list2 (cdr list2)))
+ list1)))
+
+(defun bmkp-upcase (string)
+ "`upcase', but in case of error, return original STRING.
+This works around an Emacs 20 problem that occurs if STRING contains
+binary data (weird chars)."
+ (condition-case nil (upcase string) (error string)))
+
+;; Thx to Michael Heerdegen and Michael Albinus for help with this one.
+(defun bmkp-same-file-p (file1 file2)
+ "Return non-nil if FILE1 and FILE2 name the same file.
+If either name is not absolute, then it is expanded relative to
+`default-directory' for the test."
+ (let* ((remote1 (bmkp-file-remote-p file1))
+ (remote2 (bmkp-file-remote-p file2))
+ (ignore-case-p (and (not remote1) (not remote2) ; Assume case-sensitive if remote.
+ (if (boundp 'read-file-name-completion-ignore-case)
+ (eval (car (get 'read-file-name-completion-ignore-case
+ 'standard-value)))
+ ;; From the Emacs 24 definition of `read-file-name-completion-ignore-case'.
+ (memq system-type '(ms-dos windows-nt darwin cygwin))))))
+ (and (equal remote1 remote2)
+ (if (fboundp 'file-equal-p)
+ (file-equal-p file1 file2)
+ (let ((ft1 (file-truename (expand-file-name file1)))
+ (ft2 (file-truename (expand-file-name file2))))
+ (eq t (compare-strings ft1 0 (length ft1) ft2 0 (length ft2) ignore-case-p)))))))
+
+;;; $$$$$$
+;;; (defun bmkp-same-file-p (file1 file2)
+;;; "Return non-nil if FILE1 and FILE2 name the same file.
+;;; If either name is not absolute, then it is expanded relative to
+;;; `default-directory' for the test."
+;;; (and (equal (bmkp-file-remote-p file1) (bmkp-file-remote-p file2))
+;;; (string= (file-truename (expand-file-name file1))
+;;; (file-truename (expand-file-name file2)))))
+
+;;; $$$$$$
+;;; (defun bmkp-file-remote-p (file-name)
+;;; "Returns non-nil if string FILE-NAME is likely to name a remote file."
+;;; (if (fboundp 'file-remote-p)
+;;; (file-remote-p file-name)
+;;; (and (fboundp 'ffap-file-remote-p) (ffap-file-remote-p file-name))))
+
+(defun bmkp-file-remote-p (file)
+ "Test whether FILE specifies a location on a remote system.
+Return nil or a string identifying the remote connection (ideally a
+prefix of FILE).
+
+A file is considered remote if accessing it is likely to be slower or
+less reliable than accessing local files.
+
+This is `file-remote-p', if that function is available. If not, use a
+simple match against rough remote file syntax: `/...:'.
+
+Unless `file-remote-p' is available and FILE has a `file-remote-p'
+handler that opens a remote connection, `bmkp-file-remote-p' does not
+open a remote connection."
+ (if (fboundp 'file-remote-p)
+ (file-remote-p file)
+ (and (stringp file) (string-match "\\`/[^/]+:" file) (match-string 0 file))))
+
+(defun bmkp-float-time (&optional specified-time)
+ "Same as `float-time'. (Needed for Emacs 20.)"
+ (if (fboundp 'float-time)
+ (float-time specified-time)
+ (unless specified-time (setq specified-time (current-time)))
+ (+ (* (float (nth 0 specified-time)) (expt 2 16)) (nth 1 specified-time))))
+
+(defun bmkp-string-less-case-fold-p (s1 s2)
+ "Like `string-lessp', but respect `case-fold-search'."
+ (when case-fold-search (setq s1 (bmkp-upcase s1)
+ s2 (bmkp-upcase s2)))
+ (string-lessp s1 s2))
+
+(defun bmkp-make-plain-predicate (pred &optional final-pred)
+ "Return a plain predicate that corresponds to component-predicate PRED.
+PRED and FINAL-PRED correspond to their namesakes in
+`bmkp-sort-comparer' (which see).
+
+PRED should return `(t)', `(nil)', or nil.
+
+Optional arg FINAL-PRED is the final predicate to use if PRED cannot
+decide (returns nil). If FINAL-PRED is nil, then `bmkp-alpha-p', the
+plain-predicate equivalent of `bmkp-alpha-cp' is used as the final
+predicate."
+ `(lambda (b1 b2) (let ((res (funcall ',pred b1 b2)))
+ (if res (car res) (funcall ',(or final-pred 'bmkp-alpha-p) b1 b2)))))
+
+(defun bmkp-repeat-command (command)
+ "Repeat COMMAND."
+ (require 'repeat) ; Define its vars before we let-bind them.
+ (let ((repeat-previous-repeated-command command)
+ (repeat-message-function #'ignore)
+ (last-repeatable-command 'repeat))
+ (repeat nil)))
+
+
+;;; If you need this for some reason, uncomment it.
+;;; (defun bmkp-fix-bookmark-alist-and-save ()
+;;; "Update format of `bookmark-default-file' created in summer of 2009.
+;;; You DO NOT NEED THIS, unless you happen to have used `bookmark+.el' in
+;;; the summer of 2009 to create non-file bookmarks. If you did that,
+;;; then some of those bookmarks might cause vanilla Emacs (emacs -Q) to
+;;; raise an error. You can use this command to fix that problem: it
+;;; modifies your existing `bookmark-default-file' (`~/.emacs.bmk'), after
+;;; backing up that file (suffixing the name with \"_saveNUMBER\")."
+;;; (interactive)
+;;; (require 'cl) ; For `gensym'
+;;; (if (not (yes-or-no-p
+;;; "This will modify your bookmark file, after backing it up. OK? "))
+;;; (message "OK, nothing done")
+;;; (bookmark-maybe-load-default-file)
+;;; (let ((bkup-file (concat bookmark-default-file "_" (symbol-name (gensym "save")))))
+;;; (when (condition-case err
+;;; (progn
+;;; (with-current-buffer (let ((enable-local-variables ()))
+;;; (find-file-noselect bookmark-default-file))
+;;; (write-file bkup-file))
+;;; (dolist (bmk bookmark-alist)
+;;; (let ((fn-tail (member '(filename) bmk))
+;;; (hdlr (bookmark-get-handler (car bmk))))
+;;; (cond (fn-tail
+;;; (setcar fn-tail (cons 'filename bmkp-non-file-filename)))
+;;; ((and (eq hdlr 'bmkp-jump-gnus)
+;;; (not (assoc 'filename bmk)))
+;;; (setcdr bmk (cons (cons 'filename bmkp-non-file-filename)
+;;; (cdr bmk)))))))
+;;; t) ; Be sure `dolist' exit with t to allow saving.
+;;; (error (error "No changes made. %s" (error-message-string err))))
+;;; (bookmark-save)
+;;; (message "Bookmarks file fixed. Old version is `%s'" bkup-file)))))
+
+
+;;(@* "Bookmark Entry Access Functions")
+;; *** Bookmark Entry Access Functions ***
+
+(defun bmkp-get-buffer-name (bookmark)
+ "Return the `buffer-name' entry for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+ (bookmark-prop-get bookmark 'buffer-name))
+
+(defun bmkp-get-end-position (bookmark)
+ "Return the `end-position' entry for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+ (bookmark-prop-get bookmark 'end-position))
+
+(defun bmkp-get-visits-count (bookmark)
+ "Return the `visits' count for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+ (bookmark-prop-get bookmark 'visits))
+
+(defun bmkp-get-visit-time (bookmark)
+ "Return the `time' value for BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+ ;; Should just be a prop-get, but when first implemented, we used a float
+ ;; instead of a time cons, so we need to convert any such obsolete recorded times.
+ (let ((vt (bookmark-prop-get bookmark 'time)))
+ (when (numberp vt) ; Convert mid-2009 time values (floats) to cons form.
+ (setq vt (if (boundp 'seconds-to-time)
+ (seconds-to-time vt)
+ (list (floor vt 65536) ; Inlined `seconds-to-time', for Emacs 20-21.
+ (floor (mod vt 65536))
+ (floor (* (- vt (ffloor vt)) 1000000))))))
+ vt))
+
+
+;;(@* "Sorting - General Functions")
+;; *** Sorting - General Functions ***
+
+(defun bmkp-sort-omit (alist &optional omit)
+ "Sort a copy of ALIST, omitting any elements whose keys are in OMIT.
+Return the copy.
+Do not sort if `bmkp-sort-comparer' is nil.
+This is a non-destructive operation: ALIST is not modified.
+
+Sorting is done using using `bmkp-sort-comparer'.
+If `bmkp-reverse-sort-p' is non-nil, then reverse the sort order.
+Keys are compared for sorting using `equal'.
+
+If optional arg OMIT is non-nil, then it is a list of keys. Omit from
+the return value any elements with keys in the list."
+ (lexical-let ((new-alist (bmkp-remove-omitted alist omit))
+ (sort-fn (and bmkp-sort-comparer (if (and (not (functionp bmkp-sort-comparer))
+ (consp bmkp-sort-comparer))
+ 'bmkp-multi-sort
+ bmkp-sort-comparer))))
+ (when sort-fn
+ (setq new-alist (sort new-alist (if bmkp-reverse-sort-p
+ (lambda (a b) (not (funcall sort-fn a b)))
+ sort-fn))))
+ new-alist))
+
+(defun bmkp-remove-omitted (alist &optional omit)
+ "Copy of bookmark ALIST without bookmarks whose names are in list OMIT.
+Name comparison is done using `bmkp-bookmark-name-member'.
+If optional arg OMIT is non-nil, then omit from the return value any
+elements with keys in list OMIT."
+ (let ((new ()))
+ (dolist (ii alist) (unless (bmkp-bookmark-name-member (car ii) omit) (push ii new)))
+ (nreverse new)))
+
+;;; $$$$$$ No longer used.
+;;; (defun bmkp-sort-and-remove-dups (alist &optional omit)
+;;; "Remove duplicates from a copy of ALIST, then sort it and return it.
+;;; Do not sort if `bmkp-sort-comparer' is nil.
+;;; Always remove duplicates. Keep only the first element with a given
+;;; key. This is a non-destructive operation: ALIST is not modified.
+
+;;; Sorting is done using using `bmkp-sort-comparer'.
+;;; If `bmkp-reverse-sort-p' is non-nil, then reverse the sort order.
+;;; Keys are compared for sorting using `equal'.
+;;; If optional arg OMIT is non-nil, then omit from the return value any
+;;; elements with keys in list OMIT."
+;;; (lexical-let ((new-alist (bmkp-remove-assoc-dups alist omit))
+;;; (sort-fn (and bmkp-sort-comparer (if (and (not (functionp bmkp-sort-comparer))
+;;; (consp bmkp-sort-comparer))
+;;; 'bmkp-multi-sort
+;;; bmkp-sort-comparer))))
+;;; (when sort-fn
+;;; (setq new-alist (sort new-alist (if bmkp-reverse-sort-p
+;;; (lambda (a b) (not (funcall sort-fn a b)))
+;;; sort-fn))))
+;;; new-alist))
+
+;;; KEEP this simpler version also. This uses `run-hook-with-args-until-success', but it
+;;; does not respect `bmkp-reverse-multi-sort-p'.
+;;; (defun bmkp-multi-sort (b1 b2)
+;;; "Try predicates in `bmkp-sort-comparer', in order, until one decides.
+;;; See the description of `bmkp-sort-comparer'."
+;;; (let* ((preds (append (car bmkp-sort-comparer) (cdr bmkp-sort-comparer)))
+;;; (result (run-hook-with-args-until-success 'preds b1 b2)))
+;;; (if (consp result)
+;;; (car result)
+;;; result)))
+
+;;; $$$$$$ No longer used.
+;;; (defun bmkp-remove-assoc-dups (alist &optional omit)
+;;; "Shallow copy of ALIST without elements that have duplicate keys.
+;;; Only the first element of those with the same key is kept.
+;;; Keys are compared using `equal'.
+;;; If optional arg OMIT is non-nil, then omit from the return value any
+;;; elements with keys in list OMIT."
+;;; (let ((new ()))
+;;; (dolist (ii alist) (unless (or (assoc (car ii) new) (member (car ii) omit)) (push ii new)))
+;;; (nreverse new)))
+
+
+;; This Lisp definition respects `bmkp-reverse-multi-sort-p', and can be extended.
+(defun bmkp-multi-sort (b1 b2)
+ "Try predicates in `bmkp-sort-comparer', in order, until one decides.
+See the description of `bmkp-sort-comparer'.
+If `bmkp-reverse-multi-sort-p' is non-nil, then reverse the order for
+using multi-sorting predicates."
+ (let ((preds (car bmkp-sort-comparer))
+ (final-pred (cadr bmkp-sort-comparer))
+ (result nil))
+ (when bmkp-reverse-multi-sort-p (setq preds (reverse preds)))
+ (catch 'bmkp-multi-sort
+ (dolist (pred preds)
+ (setq result (funcall pred b1 b2))
+ (when (consp result)
+ (when bmkp-reverse-multi-sort-p (setq result (list (not (car result)))))
+ (throw 'bmkp-multi-sort (car result))))
+ (and final-pred (if bmkp-reverse-multi-sort-p
+ (not (funcall final-pred b1 b2))
+ (funcall final-pred b1 b2))))))
+
+
+;; The description returned is only approximate. The effect of `bmkp-reverse-multi-sort-p' is not
+;; always intuitive, but it can often be useful. What's not always intuitive is the placement
+;; (the order) of bookmarks that are not sorted by the predicates.
+;;
+(defun bmkp-sorting-description (order)
+ "Return a string describing sort ORDER."
+ (concat
+ (if (and order bmkp-sort-comparer)
+ order
+ (concat (and order (format "(%s) " order)) "turned OFF"))
+ (cond ((not bmkp-sort-comparer) nil)
+ ((not (and (consp bmkp-sort-comparer) (consp (car bmkp-sort-comparer)))) ; Ordinary single pred.
+ (if bmkp-reverse-sort-p " (REVERSED)" ""))
+ ((not (cadr (car bmkp-sort-comparer))) ; Single predicate.
+ (if (or (and bmkp-reverse-sort-p (not bmkp-reverse-multi-sort-p))
+ (and bmkp-reverse-multi-sort-p (not bmkp-reverse-sort-p)))
+ " (REVERSED)"
+ "")
+ ;; If we wanted to distinguish the two:
+ ;; (if (and bmkp-reverse-sort-p (not bmkp-reverse-multi-sort-p))
+ ;; "; REVERSED"
+ ;; (if (and bmkp-reverse-multi-sort-p (not bmkp-reverse-sort-p))
+ ;; "; REVERSED +"
+ ;; ""))
+ )
+ ;; At least two predicates.
+ ((and bmkp-reverse-sort-p (not bmkp-reverse-multi-sort-p)) " (REVERSED)")
+ ((and bmkp-reverse-multi-sort-p (not bmkp-reverse-sort-p)) " (each pred group reversed)")
+ ((and bmkp-reverse-multi-sort-p bmkp-reverse-sort-p) " (order of pred groups reversed)")
+ (t ""))))
+
+(defun bmkp-msg-about-sort-order (order &optional prefix-msg suffix-msg)
+ "Display a message mentioning sort ORDER and direction.
+Optional arg PREFIX-MSG is prepended to the constructed message, and
+terminated with a period.
+Similarly, SUFFIX-MSG is appended, after appending \". \"."
+ (let ((msg (concat "Sorting " (bmkp-sorting-description order))))
+ (when prefix-msg (setq msg (concat prefix-msg ". " msg)))
+ (when suffix-msg (setq msg (concat msg ". " suffix-msg)))
+ (message msg)))
+
+
+;;(@* "Sorting - Commands")
+;; *** Sorting - Commands ***
+
+(defun bmkp-current-sort-order ()
+ "Current sort order or sort function, as a string, or nil if none."
+ (car (rassoc bmkp-sort-comparer bmkp-sort-orders-alist)))
+
+
+;;(@* "Sorting - General Predicates")
+;; *** Sorting - General Predicates ***
+
+(defun bmkp-annotated-cp (b1 b2)
+ "True if bookmark B1 is annotated and bookmark B2 is not.
+Return nil if incomparable as described.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((m1 (bmkp-annotated-bookmark-p b1))
+ (m2 (bmkp-annotated-bookmark-p b2)))
+ (cond ((and m1 m2) nil)
+ (m1 '(t))
+ (m2 '(nil))
+ (t nil))))
+
+(defun bmkp-flagged-cp (b1 b2)
+ "True if bookmark B1 is flagged for deletion and bookmark B2 is not.
+Return nil if incomparable as described.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((m1 (bmkp-flagged-bookmark-p b1))
+ (m2 (bmkp-flagged-bookmark-p b2)))
+ (cond ((and m1 m2) nil)
+ (m1 '(t))
+ (m2 '(nil))
+ (t nil))))
+
+(defun bmkp-marked-cp (b1 b2)
+ "True if bookmark B1 is marked and bookmark B2 is not.
+Return nil if incomparable as described.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((m1 (bmkp-marked-bookmark-p b1))
+ (m2 (bmkp-marked-bookmark-p b2)))
+ (cond ((and m1 m2) nil)
+ (m1 '(t))
+ (m2 '(nil))
+ (t nil))))
+
+(defun bmkp-modified-cp (b1 b2)
+ "True if bookmark B1 is modified and bookmark B2 is not.
+Return nil if incomparable as described.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((m1 (bmkp-modified-bookmark-p b1))
+ (m2 (bmkp-modified-bookmark-p b2)))
+ (cond ((and m1 m2) nil)
+ (m1 '(t))
+ (m2 '(nil))
+ (t nil))))
+
+(defun bmkp-tagged-cp (b1 b2)
+ "True if bookmark B1 is tagged and bookmark B2 is not.
+Return nil if incomparable as described.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((m1 (bmkp-tagged-bookmark-p b1))
+ (m2 (bmkp-tagged-bookmark-p b2)))
+ (cond ((and m1 m2) nil)
+ (m1 '(t))
+ (m2 '(nil))
+ (t nil))))
+
+(defun bmkp-visited-more-cp (b1 b2)
+ "True if bookmark B1 was visited more often than B2.
+Return nil if incomparable as described.
+
+True also if B1 was visited but B2 was not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((v1 (bmkp-get-visits-count b1))
+ (v2 (bmkp-get-visits-count b2)))
+ (cond ((and v1 v2)
+ (cond ((> v1 v2) '(t))
+ ((> v2 v1) '(nil))
+ (t nil)))
+ (v1 '(t))
+ (v2 '(nil))
+ (t nil))))
+
+(defun bmkp-bookmark-creation-cp (b1 b2)
+ "True if bookmark B1 was created more recently than B2.
+Return nil if incomparable as described.
+
+True also if B1 has a `created' entry but B2 has none.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((t1 (bookmark-prop-get b1 'created))
+ (t2 (bookmark-prop-get b2 'created)))
+ (cond ((and t1 t2)
+ (setq t1 (bmkp-float-time t1)
+ t2 (bmkp-float-time t2))
+ (cond ((> t1 t2) '(t))
+ ((> t2 t1) '(nil))
+ (t nil)))
+ (t1 '(t))
+ (t2 '(nil))
+ (t nil))))
+
+;; Not used currently.
+(defun bmkp-same-creation-time-p (b1 b2)
+ "Return non-nil if `B1 and B2 have same `created' entry.
+If neither has a `created' entry (vanilla bookmarks), then return
+non-nil if the full bookmarks are `equal'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (let ((time1 (bookmark-prop-get b1 'created))
+ (time2 (bookmark-prop-get b2 'created)))
+ (if (or time1 time2) (equal time1 time2) (equal b1 b2))))
+
+(defun bmkp-bookmark-last-access-cp (b1 b2)
+ "True if bookmark B1 was visited more recently than B2.
+Return nil if incomparable as described.
+
+True also if B1 was visited but B2 was not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((t1 (bmkp-get-visit-time b1))
+ (t2 (bmkp-get-visit-time b2)))
+ (cond ((and t1 t2)
+ (setq t1 (bmkp-float-time t1)
+ t2 (bmkp-float-time t2))
+ (cond ((> t1 t2) '(t))
+ ((> t2 t1) '(nil))
+ (t nil)))
+ (t1 '(t))
+ (t2 '(nil))
+ (t nil))))
+
+(defun bmkp-buffer-last-access-cp (b1 b2)
+ "True if bookmark B1's buffer or file was visited more recently than B2's.
+Return nil if incomparable as described.
+
+A bookmark to an existing buffer sorts before a file bookmark, even if
+the buffer has not been visited during this session.
+
+True also if B1 has a buffer but B2 does not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((buf1 (bmkp-get-buffer-name b1))
+ (buf2 (bmkp-get-buffer-name b2))
+ f1 f2 t1 t2)
+ (setq buf1 (and buf1 (get-buffer buf1))
+ buf2 (and buf2 (get-buffer buf2)))
+ (cond ((and buf1 buf2) ; Both buffers exist. See whether they were accessed.
+ (when buf1 (setq buf1 (member buf1 (buffer-list))
+ buf1 (length buf1)))
+ (when buf2 (setq buf2 (member buf2 (buffer-list))
+ buf2 (length buf2)))
+ (cond ((and buf1 buf2) ; Both were accessed. Priority to most recent access.
+ (cond ((< buf1 buf2) '(t))
+ ((< buf2 buf1) '(nil))
+ (t nil)))
+ (buf1 '(t)) ; Only buf1 was accessed.
+ (buf2 '(nil)) ; Only buf2 was accessed.
+ (t nil))) ; Neither was accessed.
+
+ (buf1 '(t)) ; Only buf1 exists.
+ (buf2 '(nil)) ; Only buf2 exists.
+ (t nil)))) ; Neither buffer exists
+
+;; EWW. Not used yet.
+(when (> emacs-major-version 24) ; Emacs 25
+
+ (defun bmkp-eww-cp (b1 b2)
+ "True if bookmark B1 sorts as an EWW URL bookmark before B2.
+Return nil if neither sorts before the other.
+
+Two EWW URL bookmarks are compared alphabetically, by their URLs.
+True also if B1 is a EWW bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((e1 (bmkp-eww-bookmark-p b1))
+ (e2 (bmkp-eww-bookmark-p b2)))
+ (cond ((and e1 e2)
+ (setq e1 (bookmark-get-filename b1)
+ e2 (bookmark-get-filename b2))
+ (cond ((string-lessp e1 e2) '(t))
+ ((string-lessp e2 e1) '(nil))
+ (t nil)))
+ (e1 '(t))
+ (e2 '(nil))
+ (t nil))))
+
+ )
+
+(defun bmkp-handler-cp (b1 b2)
+ "True if bookmark B1's handler name sorts alphabetically before B2's.
+Return nil if neither sorts before the other.
+
+Two bookmarks with handlers are compared alphabetically, by their
+handler-function names, respecting `case-fold-search'.
+True also if B1 has a handler but B2 has not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((h1 (bookmark-get-handler b1))
+ (h2 (bookmark-get-handler b2)))
+ (cond ((and h1 h2 (symbolp h1) (symbolp h2))
+ ;; Pretend woman bookmarks are man bookmarks, to keep them together.
+ (when (eq h1 'bmkp-jump-woman) (setq h1 'bmkp-jump-man))
+ (when (eq h2 'bmkp-jump-woman) (setq h2 'bmkp-jump-man))
+ (setq h1 (symbol-name h1)
+ h2 (symbol-name h2))
+ (when case-fold-search (setq h1 (bmkp-upcase h1)
+ h2 (bmkp-upcase h2)))
+ (cond ((string-lessp h1 h2) '(t))
+ ((string-lessp h2 h1) '(nil))
+ (t nil)))
+ (h1 '(t))
+ (h2 '(nil))
+ (t nil))))
+
+;; Keep the alias for a while, in case someone has it referenced in a state file.
+(defalias 'bmkp-info-cp 'bmkp-info-node-name-cp)
+(bmkp-make-obsolete 'bmkp-info-cp 'bmkp-info-node-name-cp "2017-07-03")
+
+(defun bmkp-info-node-name-cp (b1 b2)
+ "True if bookmark B1 sorts as an Info bookmark before B2.
+Return nil if neither sorts before the other.
+
+Two Info bookmarks are compared first by manual name, then by node
+name, then by position.
+
+If `bmkp-info-sort-ignores-directories-flag' is non-nil then manual
+names are used. If it is nil then absolute file names for the manuals
+are used.
+
+True also if B1 is an Info bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((i1 (bmkp-info-bookmark-p b1))
+ (i2 (bmkp-info-bookmark-p b2))
+ (fn (if bmkp-info-sort-ignores-directories-flag #'file-name-nondirectory #'abbreviate-file-name)))
+ (cond ((and i1 i2)
+ (setq i1 (funcall fn (bookmark-get-filename b1))
+ i2 (funcall fn (bookmark-get-filename b2)))
+ (when case-fold-search (setq i1 (bmkp-upcase i1)
+ i2 (bmkp-upcase i2)))
+ (cond ((string-lessp i1 i2) '(t)) ; Compare manuals (file names).
+ ((string-lessp i2 i1) '(nil))
+ (t ; Compare node names.
+ (setq i1 (bookmark-prop-get b1 'info-node)
+ i2 (bookmark-prop-get b2 'info-node))
+ (cond ((string-lessp i1 i2) '(t))
+ ((string-lessp i2 i1) '(nil))
+ (t
+ (setq i1 (bookmark-get-position b1)
+ i2 (bookmark-get-position b2))
+ (cond ((or (not i1) (not i2)) '(t)) ; Fallback if no `position' entry.
+ ((<= i1 i2) '(t))
+ ((< i2 i1) '(nil))))))))
+ (i1 '(t))
+ (i2 '(nil))
+ (t nil))))
+
+(defun bmkp-info-position-cp (b1 b2)
+ "True if bookmark B1 sorts as Info bookmark before B2 in book order.
+Return nil if neither sorts before the other.
+
+Two Info bookmarks are compared first by manual name, then by position
+in the file.
+
+If `bmkp-info-sort-ignores-directories-flag' is non-nil then manual
+names are used. If it is nil then absolute file names for the manuals
+are used.
+
+True also if B1 is an Info bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((i1 (bmkp-info-bookmark-p b1))
+ (i2 (bmkp-info-bookmark-p b2))
+ (fn (if bmkp-info-sort-ignores-directories-flag #'file-name-nondirectory #'abbreviate-file-name)))
+ (cond ((and i1 i2)
+ (setq i1 (funcall fn (bookmark-get-filename b1))
+ i2 (funcall fn (bookmark-get-filename b2)))
+ (when case-fold-search (setq i1 (bmkp-upcase i1)
+ i2 (bmkp-upcase i2)))
+ (cond ((string-lessp i1 i2) '(t)) ; Compare manuals (file names).
+ ((string-lessp i2 i1) '(nil))
+ (t ; Compare positions.
+ (setq i1 (bookmark-get-position b1)
+ i2 (bookmark-get-position b2))
+ (cond ((or (not i1) (not i2)) '(t)) ; Fallback if no `position' entry.
+ ((<= i1 i2) '(t))
+ ((< i2 i1) '(nil))))))
+ (i1 '(t))
+ (i2 '(nil))
+ (t nil))))
+
+(defun bmkp-gnus-cp (b1 b2)
+ "True if bookmark B1 sorts as a Gnus bookmark before B2.
+Return nil if neither sorts before the other.
+
+Two Gnus bookmarks are compared first by Gnus group name, then by
+article number, then by message ID.
+True also if B1 is a Gnus bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((g1 (bmkp-gnus-bookmark-p b1))
+ (g2 (bmkp-gnus-bookmark-p b2)))
+ (cond ((and g1 g2)
+ (setq g1 (bookmark-prop-get b1 'group)
+ g2 (bookmark-prop-get b2 'group))
+ (cond ((string-lessp g1 g2) '(t)) ; Compare groups.
+ ((string-lessp g2 g1) '(nil))
+ (t ; Compare article numbers.
+ (setq g1 (bookmark-prop-get b1 'article)
+ g2 (bookmark-prop-get b2 'article))
+ (cond ((< g1 g2) '(t))
+ ((< g2 g1) '(nil))
+ (t
+ (setq g1 (bookmark-prop-get b1 'message-id)
+ g2 (bookmark-prop-get b2 'message-id))
+ (cond ((string-lessp g1 g2) '(t)) ; Compare message IDs.
+ ((string-lessp g2 g1) '(nil))
+ (t nil)))))))
+ (g1 '(t))
+ (g2 '(nil))
+ (t nil))))
+
+(defun bmkp-url-cp (b1 b2)
+ "True if bookmark B1 sorts as a URL bookmark before B2.
+Return nil if neither sorts before the other.
+
+Two URL bookmarks are compared alphabetically, by their URLs.
+True also if B1 is a URL bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((u1 (bmkp-url-bookmark-p b1))
+ (u2 (bmkp-url-bookmark-p b2)))
+ (cond ((and u1 u2)
+ (setq u1 (or (bookmark-prop-get b1 'location) (bookmark-get-filename b1))
+ u2 (or (bookmark-prop-get b2 'location) (bookmark-get-filename b2)))
+ (cond ((string-lessp u1 u2) '(t))
+ ((string-lessp u2 u1) '(nil))
+ (t nil)))
+ (u1 '(t))
+ (u2 '(nil))
+ (t nil))))
+
+;; Not used now.
+(defun bmkp-w3m-cp (b1 b2)
+ "True if bookmark B1 sorts as a W3M URL bookmark before B2.
+Return nil if neither sorts before the other.
+
+Two W3M URL bookmarks are compared alphabetically, by their URLs.
+True also if B1 is a W3M bookmark but B2 is not.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((w1 (bmkp-w3m-bookmark-p b1))
+ (w2 (bmkp-w3m-bookmark-p b2)))
+ (cond ((and w1 w2)
+ (setq w1 (bookmark-get-filename b1)
+ w2 (bookmark-get-filename b2))
+ (cond ((string-lessp w1 w2) '(t))
+ ((string-lessp w2 w1) '(nil))
+ (t nil)))
+ (w1 '(t))
+ (w2 '(nil))
+ (t nil))))
+
+(defun bmkp-position-cp (b1 b2)
+ "True if the `position' of B1 is not greater than that of B2.
+Return nil if B1 and B2 do not bookmark the same buffer or they have
+the same `position' value.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((buf1 (bmkp-get-buffer-name b1))
+ (buf2 (bmkp-get-buffer-name b2)))
+ (and buf1 buf2 (equal buf1 buf2)
+ (let ((i1 (bookmark-get-position b1))
+ (i2 (bookmark-get-position b2)))
+ (cond ((or (not i1) (not i2)) '(t)) ; Fallback if no `position' entry.
+ ((<= i1 i2) '(t))
+ ((< i2 i1) '(nil)))))))
+
+(defun bmkp-alpha-cp (b1 b2)
+ "True if bookmark B1's name sorts alphabetically before B2's.
+Return nil if neither sorts before the other.
+
+The bookmark names are compared, respecting `case-fold-search'.
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((s1 (car b1))
+ (s2 (car b2)))
+ (when case-fold-search (setq s1 (bmkp-upcase s1)
+ s2 (bmkp-upcase s2)))
+ (cond ((string-lessp s1 s2) '(t))
+ ((string-lessp s2 s1) '(nil))
+ (t nil))))
+
+;; Do not use `bmkp-make-plain-predicate', because it falls back on `bookmark-alpha-p'.
+;; Return nil if `bookmark-alpha-cp' cannot decide.
+(defun bmkp-alpha-p (b1 b2)
+ "True if bookmark B1's name sorts alphabetically before B2's.
+The bookmark names are compared, respecting `case-fold-search'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (car (bmkp-alpha-cp b1 b2)))
+
+
+;;(@* "Sorting - File-Name Predicates")
+;; *** Sorting - File-Name Predicates ***
+
+(defun bmkp-file-alpha-cp (b1 b2)
+ "True if bookmark B1's file name sorts alphabetically before B2's.
+Return nil if neither sorts before the other.
+
+The file names are shortened using `abbreviate-file-name', then they
+are compared respecting `case-fold-search'.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (let ((f1 (bmkp-file-bookmark-p b1))
+ (f2 (bmkp-file-bookmark-p b2)))
+ (cond ((and f1 f2)
+ ;; Call `abbreviate-file-name' mainly to get letter case right per platform.
+ (setq f1 (abbreviate-file-name (bookmark-get-filename b1))
+ f2 (abbreviate-file-name (bookmark-get-filename b2)))
+ (when case-fold-search (setq f1 (bmkp-upcase f1)
+ f2 (bmkp-upcase f2)))
+ (cond ((string-lessp f1 f2) '(t))
+ ((string-lessp f2 f1) '(nil))
+ (t nil)))
+ (f1 '(t))
+ (f2 '(nil))
+ (t nil))))
+
+;; We define all file-attribute predicates, in case you want to use them.
+;;
+;; `bmkp-file-attribute-0-cp' - type
+;; `bmkp-file-attribute-1-cp' - links
+;; `bmkp-file-attribute-2-cp' - uid
+;; `bmkp-file-attribute-3-cp' - gid
+;; `bmkp-file-attribute-4-cp' - last access time
+;; `bmkp-file-attribute-5-cp' - last update time
+;; `bmkp-file-attribute-6-cp' - last status change
+;; `bmkp-file-attribute-7-cp' - size
+;; `bmkp-file-attribute-8-cp' - modes
+;; `bmkp-file-attribute-9-cp' - gid change
+;; `bmkp-file-attribute-10-cp' - inode
+;; `bmkp-file-attribute-11-cp' - device
+;;
+(bmkp-define-file-sort-predicate 0) ; Type: file, symlink, dir
+(bmkp-define-file-sort-predicate 1) ; Links
+(bmkp-define-file-sort-predicate 2) ; Uid
+(bmkp-define-file-sort-predicate 3) ; Gid
+(bmkp-define-file-sort-predicate 4) ; Last access time
+(bmkp-define-file-sort-predicate 5) ; Last modification time
+(bmkp-define-file-sort-predicate 6) ; Last status-change time
+(bmkp-define-file-sort-predicate 7) ; Size
+(bmkp-define-file-sort-predicate 8) ; Modes
+(bmkp-define-file-sort-predicate 9) ; Gid would change if re-created
+(bmkp-define-file-sort-predicate 10) ; Inode
+(bmkp-define-file-sort-predicate 11) ; Device
+
+(defun bmkp-local-file-accessed-more-recently-cp (b1 b2)
+ "True if bookmark B1's local file was accessed more recently than B2's.
+Return nil if neither sorts before the other.
+
+A local file sorts before a remote file, which sorts before other
+bookmarks. Two remote files are considered incomparable - their
+access times are not examined.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (cond ((and (bmkp-local-file-bookmark-p b1) (bmkp-local-file-bookmark-p b2))
+ (bmkp-cp-not (bmkp-file-attribute-4-cp b1 b2)))
+ ((bmkp-local-file-bookmark-p b1) '(t))
+ ((bmkp-local-file-bookmark-p b2) '(nil))
+ ((and (bmkp-remote-file-bookmark-p b1)
+ (bmkp-remote-file-bookmark-p b2)) nil)
+ ((bmkp-remote-file-bookmark-p b1) '(t))
+ ((bmkp-remote-file-bookmark-p b2) '(nil))
+ (t nil)))
+
+(defun bmkp-local-file-updated-more-recently-cp (b1 b2)
+ "True if bookmark B1's local file was updated more recently than B2's.
+Return nil if neither sorts before the other.
+
+A local file sorts before a remote file, which sorts before other
+bookmarks. Two remote files are considered incomparable - their
+update times are not examined.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (cond ((and (bmkp-local-file-bookmark-p b1) (bmkp-local-file-bookmark-p b2))
+ (bmkp-cp-not (bmkp-file-attribute-5-cp b1 b2)))
+ ((bmkp-local-file-bookmark-p b1) '(t))
+ ((bmkp-local-file-bookmark-p b2) '(nil))
+ ((and (bmkp-remote-file-bookmark-p b1)
+ (bmkp-remote-file-bookmark-p b2)) nil)
+ ((bmkp-remote-file-bookmark-p b1) '(t))
+ ((bmkp-remote-file-bookmark-p b2) '(nil))
+ (t nil)))
+
+(defun bmkp-local-file-size-cp (b1 b2)
+ "True if bookmark B1's local file is larger than B2's.
+Return nil if neither sorts before the other.
+
+A local file sorts before a remote file, which sorts before other
+bookmarks. Two remote files are considered incomparable - their
+sizes are not examined.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (cond ((and (bmkp-local-file-bookmark-p b1) (bmkp-local-file-bookmark-p b2))
+ (bmkp-cp-not (bmkp-file-attribute-7-cp b1 b2)))
+ ((bmkp-local-file-bookmark-p b1) '(t))
+ ((bmkp-local-file-bookmark-p b2) '(nil))
+ ((and (bmkp-remote-file-bookmark-p b1)
+ (bmkp-remote-file-bookmark-p b2)) nil)
+ ((bmkp-remote-file-bookmark-p b1) '(t))
+ ((bmkp-remote-file-bookmark-p b2) '(nil))
+ (t nil)))
+
+(defun bmkp-local-file-type-cp (b1 b2)
+ "True if bookmark B1 sorts by local file type before B2.
+Return nil if neither sorts before the other.
+
+For two local files, a file sorts before a symlink, which sorts before
+a directory.
+
+A local file sorts before a remote file, which sorts before other
+bookmarks. Two remote files are considered incomparable - their file
+types are not examined.
+
+Reverse the roles of B1 and B2 for a false value.
+A true value is returned as `(t)', a false value as `(nil)'.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ (setq b1 (bmkp-get-bookmark b1)
+ b2 (bmkp-get-bookmark b2))
+ (cond ((and (bmkp-local-file-bookmark-p b1) (bmkp-local-file-bookmark-p b2))
+ (bmkp-file-attribute-0-cp b1 b2))
+ ((bmkp-local-file-bookmark-p b1) '(t))
+ ((bmkp-local-file-bookmark-p b2) '(nil))
+ ((and (bmkp-remote-file-bookmark-p b1)
+ (bmkp-remote-file-bookmark-p b2)) nil)
+ ((bmkp-remote-file-bookmark-p b1) '(t))
+ ((bmkp-remote-file-bookmark-p b2) '(nil))
+ (t nil)))
+
+(defun bmkp-cp-not (truth)
+ "Return the negation of boolean value TRUTH.
+If TRUTH is (t), return (nil), and vice versa.
+If TRUTH is nil, return nil."
+ (and truth (if (car truth) '(nil) '(t))))
+
+
+;;(@* "Indirect Bookmarking Functions")
+;; *** Indirect Bookmarking Functions ***
+
+;;;###autoload (autoload 'bmkp-url-target-set "bookmark+")
+(defun bmkp-url-target-set (url &optional arg name/prefix no-overwrite-p no-refresh-p msg-p)
+ ; Bound globally to `C-x x c u'.
+ "Set a bookmark for a URL. Return the bookmark.
+Interactively you are prompted for the URL. Completion is available.
+Use `M-n' to pick up the url at point as the default.
+
+You are also prompted for the bookmark name. But with a non-negative
+prefix arg, you are prompted only for a bookmark-name prefix. In that
+case, the bookmark name is the prefix followed by the URL.
+
+When entering a bookmark name you can use completion against existing
+names. This completion is lax, so you can easily edit an existing
+name. See `bookmark-set' for particular keys available during this
+input.
+
+If you use a numeric prefix arg, such as `C-1', instead of plain
+`C-u', then a new bookmark is created if a bookmark of the same name
+already exists: an existing bookmark is not overwritten. You can thus
+have multiple bookmarks with the same name, which target different
+URLs.
+
+Summary of prefix argument behavior:
+
+* None: Provide full bookmark name. Overwrite existing bookmark
+* Plain `C-u': Provide name prefix only. Overwrite existing bookmark
+* N >= 0: Provide name prefix only. Do not overwrite.
+* N < 0: Provide full bookmark name. Do not overwrite.
+
+Non-interactively:
+* Numeric ARG >= 0 means NAME/PREFIX is a bookmark-name prefix.
+* NAME/PREFIX is the bookmark name or its prefix (the suffix = URL).
+* Non-nil NO-OVERWRITE-P means do not overwrite an existing bookmark.
+* Non-nil NO-REFRESH-P means do not refresh/rebuild the bookmark-list
+ display.
+* Non-nil MSG-P means display a status message."
+ (interactive
+ (let* ((icicle-unpropertize-completion-result-flag t)
+ (default-url (or (bmkp-thing-at-point 'url)
+ (and (fboundp 'url-get-url-at-point)
+ (url-get-url-at-point))
+ ;; TEMPORARY hack to work around Emacs bug #44822.
+ "https://example.com"))
+ (parg current-prefix-arg)
+ (prefix-only (and parg (natnump (prefix-numeric-value parg))))
+ (no-overw (and parg (atom current-prefix-arg))))
+ (list (if (require 'ffap nil t)
+ (ffap-read-file-or-url "URL: " default-url)
+ (read-from-minibuffer "URL: " nil nil nil nil default-url))
+ prefix-only
+ (if prefix-only
+ (read-string "Prefix for bookmark name: ")
+ (bmkp-completing-read-lax "Bookmark name"))
+ no-overw
+ nil
+ 'MSG)))
+ (unless name/prefix (setq name/prefix ""))
+ (let ((bookmark-make-record-function (cond ((and (eq major-mode 'eww-mode)
+ (fboundp 'bmkp-make-eww-record)) ; Emacs 25+
+ 'bmkp-make-eww-record)
+ ((eq major-mode 'w3m-mode) 'bmkp-make-w3m-record)
+ (t `(lambda () (bmkp-make-url-browse-record ',url)))))
+ bmk failure)
+ (condition-case err
+ (setq bmk (bookmark-store (if arg (concat name/prefix url) name/prefix)
+ (cdr (bookmark-make-record)) no-overwrite-p no-refresh-p (not msg-p)))
+ (error (setq failure err)))
+ (when failure (error "Failed to create bookmark for `%s':\n%s\n" url failure))
+ bmk)) ; Return the bookmark.
+
+;;;###autoload (autoload 'bmkp-file-target-set "bookmark+")
+(defun bmkp-file-target-set (file &optional arg name/prefix no-overwrite no-refresh-p msg-p)
+ ; Bound to `C-x x c f'
+ "Set a bookmark for FILE. Return the bookmark.
+The bookmarked position is the beginning of the file (0).
+Interactively you are prompted for FILE. Completion is available.
+You can use `M-n' to pick up the file name at point, or if none then
+the visited file.
+
+FILE can also be a directory name. In that case set a bookmark for
+the directory.
+
+You are also prompted for the bookmark name. But with a non-negative
+prefix arg, you are prompted only for a bookmark-name prefix. In that
+case, the bookmark name is the prefix followed by the nondirectory
+part of FILE (or of its `directory-file-name', if a directory name).
+
+When entering a bookmark name you can use completion against existing
+names. This completion is lax, so you can easily edit an existing
+name. See `bookmark-set' for particular keys available during this
+input.
+
+If you use a numeric prefix arg, such as `C-1', instead of plain
+`C-u', then a new bookmark is created if a bookmark of the same name
+already exists: an existing bookmark is not overwritten. You can thus
+have multiple bookmarks with the same name, which target different
+URLs.
+
+Summary of prefix argument behavior:
+
+* None: Provide full bookmark name. Overwrite existing bookmark
+* Plain `C-u': Provide name prefix only. Overwrite existing bookmark
+* N >= 0: Provide name prefix only. Do not overwrite.
+* N < 0: Provide full bookmark name Do not overwrite.
+
+Non-interactively:
+* Numeric ARG >= 0 means NAME/PREFIX is a bookmark-name prefix.
+* NAME/PREFIX is the bookmark name or its prefix.
+* Non-nil NO-OVERWRITE-P means do not overwrite an existing bookmark.
+* Non-nil NO-REFRESH-P means do not refresh/rebuild the bookmark-list
+ display.
+* Non-nil MSG-P means show a warning message if file does not exist."
+ (interactive
+ (let* ((icicle-unpropertize-completion-result-flag t)
+ (parg current-prefix-arg)
+ (prefix-only (and parg (natnump (prefix-numeric-value parg))))
+ (no-overw (and parg (atom current-prefix-arg))))
+ (list (read-file-name "File: " nil
+ (or (if (boundp 'file-name-at-point-functions) ; In `files.el', Emacs 23.2+.
+ (run-hook-with-args-until-success 'file-name-at-point-functions)
+ (bmkp-ffap-guesser))
+ (bmkp-thing-at-point 'filename)
+ (buffer-file-name)))
+ prefix-only
+ (if prefix-only
+ (read-string "Prefix for bookmark name: ")
+ (bmkp-completing-read-lax "Bookmark name"))
+ no-overw
+ nil
+ 'MSG)))
+ (unless name/prefix (setq name/prefix ""))
+ (let ((bookmark-make-record-function (bmkp-make-record-for-target-file file))
+ bmk failure)
+ (condition-case err
+ (setq bmk (bookmark-store (if arg
+ (concat name/prefix
+ (file-name-nondirectory (if (file-directory-p file)
+ (directory-file-name file)
+ file)))
+ name/prefix)
+ (cdr (bookmark-make-record)) no-overwrite no-refresh-p (not msg-p)))
+ (error (setq failure (error-message-string err))))
+ (when failure (error "Failed to create bookmark for `%s':\n%s\n" file failure))
+ (unless no-refresh-p (bmkp-refresh/rebuild-menu-list bmk (not msg-p)))
+ (when (and msg-p (not (file-exists-p file)))
+ (message "File name is now bookmarked, but no such file yet: `%s'" (expand-file-name file)))
+ bmk)) ; Return the bookmark.
+
+(defun bmkp-make-record-for-target-file (file)
+ "Return a function that creates a bookmark record for FILE.
+The bookmarked position will be the beginning of the file."
+ ;; $$$$$$ Maybe need a way to bypass default handler, at least for autofiles.
+ ;; Doesn't seem to make much sense to use a handler such as a shell cmd in this context. (?)
+ (set-text-properties 0 (length file) () file)
+ (let ((default-handler (condition-case nil (bmkp-default-handler-for-file file) (error nil)))
+ (common `((filename . ,file)
+ (position . 0)
+ (created . ,(current-time)))))
+ (cond (default-handler ; User default handler
+ `(lambda () ',(append common `((file-handler . ,default-handler)))))
+ ;; Non-user defaults.
+ ((and (require 'image nil t) (require 'image-mode nil t) ; Image
+ (condition-case nil (image-type file) (error nil)))
+ ;; Last two lines of function are from `image-bookmark-make-record'.
+ ;; But don't use that directly, because it uses
+ ;; `bookmark-make-record-default', which gets nil for `filename'.
+
+ ;; NEED TO KEEP THIS CODE SYNC'D WITH `diredp-bookmark'.
+ `(lambda ()
+ ',(append common `((image-type . ,(image-type file)) (handler . image-bookmark-jump)))))
+ ((let ((case-fold-search t)) (bmkp-string-match-p "\\([.]au$\\|[.]wav$\\)" file)) ; Sound
+ ;; Obsolete: `(lambda () '((filename . ,file) (handler . bmkp-sound-jump))))
+ `(lambda () ',(append common '((file-handler . play-sound-file)))))
+ (t
+ `(lambda () ',common)))))
+
+(when (fboundp 'file-cache-add-file)
+ (defadvice file-cache-add-file (around bmkp-autofile-filecache activate)
+ "Respect option `bmkp-autofile-filecache'."
+ (cond ((eq bmkp-autofile-filecache 'autofile-only)
+ (bmkp-autofile-set
+ (ad-get-arg 0) nil nil
+ 'NO-REFRESH-P))
+ ((eq bmkp-autofile-filecache 'autofile+cache)
+ (progn
+ ad-do-it
+ (bmkp-autofile-set
+ (ad-get-arg 0) nil nil
+ 'NO-REFRESH-P 'MSG-P)))
+ ((eq bmkp-autofile-filecache 'cache-only)
+ ad-do-it))))
+
+(defun bmkp-find-file-invoke-bookmark-if-autofile ()
+ "Invoke the autofile bookmark associated with the visited file.
+This is added to `find-file-hook' when option
+`bmkp-autofile-access-invokes-bookmark-flag' is non-nil. When invoked
+it causes regular file access to invoke the associated bookmark. This
+has the effect of updating the bookmark data, such as the number of
+visits."
+ (let* ((buf-file (buffer-file-name))
+ (bmk (bmkp-get-bookmark-in-alist (file-name-nondirectory buf-file)
+ t
+ (bmkp-autofile-alist-only)))
+ (bmk-file (and bmk (bookmark-get-filename bmk))))
+ (when (and bmk-file (bmkp-same-file-p buf-file bmk-file))
+ (let ((bmkp-autofile-access-invokes-bookmark-flag nil)) ; Just to be sure.
+ (bookmark--jump-via bmk 'ignore)))))
+
+;;;###autoload (autoload 'bmkp-bookmark-a-file "bookmark+")
+(defalias 'bmkp-bookmark-a-file 'bmkp-autofile-set)
+;;;###autoload (autoload 'bmkp-autofile-set "bookmark+")
+(defun bmkp-autofile-set (file &optional dir prefix no-refresh-p msg-p) ; Bound to `C-x x c a'
+ "Set a bookmark for FILE, autonaming the bookmark for the file.
+Return the bookmark.
+Interactively, you are prompted for FILE. You can use `M-n' to pick
+up the file name at point or the visited file.
+
+The bookmark name is the nondirectory part of FILE, but with a prefix
+arg you are also prompted for a PREFIX string to prepend to the
+bookmark name. The bookmarked position is the beginning of the file.
+
+Note that if you provide PREFIX then the bookmark will not satisfy
+`bmkp-autofile-bookmark-p' unless you provide the same PREFIX to that
+predicate.
+
+The bookmark's file name is FILE if absolute. If relative then it is
+FILE expanded in DIR, if non-nil, or in the current directory
+\(`default-directory').
+
+If a bookmark with the same name already exists for the same file name
+then do nothing.
+
+Otherwise, create a new bookmark for the file, even if a bookmark with
+the same name already exists. This means that you can have more than
+one autofile bookmark with the same bookmark name and the same
+relative file name (nondirectory part), but with different absolute
+file names.
+
+Non-interactively:
+ - Non-nil NO-REFRESH-P means do not refresh/rebuild the bookmark-list
+ display.
+ - Non-nil optional arg MSG-P means display status messages."
+ (interactive
+ (list (let ((icicle-unpropertize-completion-result-flag t))
+ (read-file-name "File: " nil
+ (if (or (> emacs-major-version 23)
+ (and (= emacs-major-version 23) (> emacs-minor-version 1)))
+ (let ((deflts ())
+ def)
+ (when (setq def (buffer-file-name)) (push def deflts))
+ (when (setq def (bmkp-thing-at-point 'filename)) (push def deflts))
+ (when (setq def (bmkp-ffap-guesser)) (push def deflts))
+ (when (and (boundp 'file-name-at-point-functions)
+ (setq def (run-hook-with-args-until-success
+ 'file-name-at-point-functions)))
+ (push def deflts))
+ deflts)
+ (or (if (boundp 'file-name-at-point-functions) ; In `files.el', Emacs 23.2+.
+ (run-hook-with-args-until-success 'file-name-at-point-functions)
+ (bmkp-ffap-guesser))
+ (bmkp-thing-at-point 'filename)
+ (buffer-file-name)))))
+ nil
+ (and current-prefix-arg (read-string "Prefix for bookmark name: "))
+ nil
+ 'MSG))
+ (let* ((dir-to-use (if (file-name-absolute-p file)
+ (file-name-directory file)
+ (or dir default-directory)))
+ ;; Look for existing bookmark with same name, same file, in `dir-to-use'.
+ (bmk (bmkp-get-autofile-bookmark file dir-to-use prefix)))
+ ;; If BMK was found, then instead of doing nothing we could replace the existing BMK with a new
+ ;; one, as follows:
+ ;; (let ((bookmark-make-record-function (bmkp-make-record-for-target-file file)))
+ ;; (bmkp-replace-existing-bookmark bmk)) ; Update the existing bookmark.
+ (if (not bmk)
+ ;; Create a new bookmark, and return it.
+ (bmkp-file-target-set (expand-file-name file dir-to-use) t prefix 'NO-OVERWRITE no-refresh-p msg-p)
+ (when msg-p (message "Autofile bookmark set for `%s'" file))
+ bmk))) ; Return the bookmark.
+
+(defun bmkp-get-autofile-bookmark (file &optional dir prefix)
+ "Return an existing autofile bookmark for FILE, or nil if there is none.
+The bookmark name is PREFIX prepended to the nondirectory part of
+FILE (or of FILE's `directory-file-name', if FILE is a directory).
+
+If PREFIX is nil then it acts like an empty prefix (\"\").
+
+The directory part of bookmark entry `filename' is the directory part
+of FILE, if FILE is absolute. Otherwise, it is DIR, if non-nil, or
+`default-directory' otherwise.
+
+FILE and the `filename' entry of the bookmark returned are the same,
+except possibly for their directory parts (see previous)."
+ (let* ((fname (file-name-nondirectory (if (file-directory-p file)
+ (directory-file-name file)
+ file)))
+ (bname (if prefix (concat prefix fname) fname))
+ (dir-to-use (if (file-name-absolute-p file)
+ (file-name-directory file)
+ (or dir default-directory))))
+ ;; Look for existing bookmark with same name, same file, in `dir-to-use'.
+ (catch 'bmkp-get-autofile-bookmark
+ (dolist (bmk bookmark-alist)
+ (when (string= bname (bmkp-bookmark-name-from-record bmk))
+ (let* ((bfil (bookmark-get-filename bmk))
+ (bdir (and bfil (file-name-directory bfil))))
+ (when (and bfil bdir (bmkp-same-file-p bdir dir-to-use) (bmkp-same-file-p bfil file))
+ (throw 'bmkp-get-autofile-bookmark bmk))))) ; Return the bookmark.
+ nil)))
+
+;;;###autoload (autoload 'bmkp-tag-a-file "bookmark+")
+(defalias 'bmkp-tag-a-file 'bmkp-autofile-add-tags) ; Bound to `C-x x t + a'
+;;;###autoload (autoload 'bmkp-autofile-add-tags "bookmark+")
+(defun bmkp-autofile-add-tags (file tags &optional dir prefix no-update-p msg-p)
+ "Add TAGS to the autofile bookmark for FILE (a file or directory name).
+Return the number of tags added.
+
+If there is no autofile bookmark for FILE, create one.
+Interactively, you are prompted for FILE and then TAGS.
+When prompted for FILE you can use `M-n' to pick up the file name at
+point, or if none then the visited file.
+
+With a non-negative prefix argument, you are prompted for a file-name
+prefix, as in `bmkp-autofile-set'.
+
+When prompted for tags, hit `RET' to enter each tag, then hit `RET'
+again after the last tag. You can use completion to enter each tag.
+Completion is lax: you are not limited to existing tags.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a non-positive prefix argument if you want to refresh them.
+
+Non-interactively:
+ - TAGS is a list of strings.
+ - DIR and PREFIX are as for `bmkp-autofile-set'.
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist', do not
+ update the modification count and maybe save bookmarks, and do not
+ refresh/rebuild the bookmark-list display
+ - Non-nil MSG-P means display a message about the addition."
+ (interactive
+ (list (let ((icicle-unpropertize-completion-result-flag t))
+ (read-file-name "File or directory to tag: " nil
+ (or (if (boundp 'file-name-at-point-functions) ; In `files.el', Emacs 23.2+.
+ (run-hook-with-args-until-success 'file-name-at-point-functions)
+ (bmkp-ffap-guesser))
+ (bmkp-thing-at-point 'filename)
+ (buffer-file-name))))
+ (bmkp-read-tags-completing nil nil (and current-prefix-arg
+ (<= (prefix-numeric-value current-prefix-arg) 0)))
+ nil
+ (and current-prefix-arg (wholenump (prefix-numeric-value current-prefix-arg))
+ (read-string "Prefix for bookmark name: "))
+ nil
+ 'MSG))
+ (bmkp-add-tags (bmkp-autofile-set file dir prefix no-update-p) tags no-update-p msg-p))
+
+;;;###autoload (autoload 'bmkp-untag-a-file "bookmark+")
+(defalias 'bmkp-untag-a-file 'bmkp-autofile-remove-tags) ; Bound to `C-x x t - a'
+;;;###autoload (autoload 'bmkp-autofile-remove-tags "bookmark+")
+(defun bmkp-autofile-remove-tags (file tags &optional dir prefix no-update-p msg-p)
+ "Remove TAGS from autofile bookmark for FILE.
+Return the number of tags removed.
+
+Interactively, you are prompted for TAGS and then FILE.
+With Emacs 22 and later, only files with at least one of the given
+tags are candidates.
+
+When prompted for FILE you can use `M-n' to pick up the file name at
+point, or if none then the visited file.
+
+With a non-negative prefix argument, you are prompted for a file-name
+prefix, as in `bmkp-autofile-set'.
+
+
+When prompted for tags, hit `RET' to enter each tag to be removed,
+then hit `RET' again after the last tag. You can use completion to
+enter each tag.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a non-positive prefix argument if you want to refresh them.
+
+Non-interactively:
+ - TAGS is a list of strings.
+ - DIR and PREFIX are as for `bmkp-autofile-set'.
+ - Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist', do not
+ update the modification count and maybe save bookmarks, and do not
+ refresh/rebuild the bookmark-list display
+ - Non-nil MSG-P means display a message about the removal."
+ (interactive
+ (lexical-let* ((pref
+ (and current-prefix-arg (wholenump (prefix-numeric-value current-prefix-arg))
+ (read-string "Prefix for bookmark name: ")))
+ (tgs
+ (bmkp-read-tags-completing nil nil (and current-prefix-arg
+ (<= (prefix-numeric-value current-prefix-arg) 0))))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (fil (condition-case nil
+ (read-file-name
+ "File: " nil
+ (or (if (boundp 'file-name-at-point-functions) ; In `files.el', Emacs 23.2+.
+ (run-hook-with-args-until-success 'file-name-at-point-functions)
+ (bmkp-ffap-guesser))
+ (bmkp-thing-at-point 'filename)
+ (buffer-file-name))
+ t nil (lambda (ff) ; PREDICATE - only for Emacs 22+.
+ (let* ((bmk (bmkp-get-autofile-bookmark ff nil pref))
+ (btgs (and bmk (bmkp-get-tags bmk))))
+ (and btgs (catch 'bmkp-autofile-remove-tags-pred
+ (dolist (tag tgs)
+ (when (not (member tag btgs))
+ (throw 'bmkp-autofile-remove-tags-pred nil)))
+ t)))))
+ (error (read-file-name "File: " nil (or (bmkp-ffap-guesser)
+ (bmkp-thing-at-point 'filename)
+ (buffer-file-name)))))))
+ (list fil tgs nil pref nil 'MSG)))
+ (bmkp-remove-tags (bmkp-autofile-set file dir prefix no-update-p) tags no-update-p msg-p))
+
+;;;###autoload (autoload 'bmkp-purge-notags-autofiles "bookmark+")
+(defun bmkp-purge-notags-autofiles (&optional prefix msg-p) ; Not bound
+ "Delete all autofile bookmarks that have no tags.
+With a prefix arg, you are prompted for a PREFIX for the bookmark name.
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive (if (not (y-or-n-p "Delete all autofile bookmarks that do not have tags? "))
+ (error "OK - deletion canceled")
+ (list (and current-prefix-arg (read-string "Prefix for bookmark name: ")) 'MSG)))
+ (let ((bmks (bmkp-autofile-alist-only prefix))
+ (bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag)) ; Save only after `dolist'.
+ record tags)
+ ;; Needs Bookmark+ version of `bookmark-delete', which accepts a bookmark, not just its name.
+ (dolist (bmk bmks)
+ (when (and (setq tags (assq 'tags (bmkp-bookmark-data-from-record bmk)))
+ (or (not tags) (null (cdr tags))))
+ (bookmark-delete bmk 'BATCHP)))) ; Do not refresh list here - do it after iterate.
+ (bmkp-tags-list) ; Update the tags cache now, after iterate.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh/rebuild-menu-list nil (not msg-p))) ; Refresh now, after iterate.
+
+
+;; $$$$$$ Not used currently.
+(defun bmkp-replace-existing-bookmark (bookmark)
+ "Replace existing BOOKMARK with a new one of the same name.
+Return the new bookmark.
+BOOKMARK is a full bookmark record, not a bookmark name.
+
+This replaces the existing bookmark data with the data for a new
+bookmark, based on `bookmark-make-record-function'. It also updates
+the `bmkp-full-record' on the bookmark name (without otherwise
+changing the name)."
+ (let (failure)
+ (condition-case err
+ (progn ; Code similar to `bookmark-store'.
+ (setcdr bookmark (cdr (bookmark-make-record)))
+ (bmkp-maybe-save-bookmarks)
+ ;; Put the full bookmark on its name as property `bmkp-full-record'.
+ ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
+ ;; If it needs to be stripped, that will be done when saving.
+ (let ((bname (bmkp-bookmark-name-from-record bookmark)))
+ (put-text-property 0 (length bname) 'bmkp-full-record bookmark bname)
+ ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+ (unless (memq bookmark bmkp-modified-bookmarks)
+ (setq bmkp-modified-bookmarks (cons bookmark bmkp-modified-bookmarks)))
+ (setq bookmark-current-bookmark bname))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P))
+ (error (setq failure (error-message-string err))))
+ (if (not failure)
+ bookmark ; Return the bookmark.
+ (error "Failed to update bookmark `%s':\n%s\n"
+ (bmkp-bookmark-name-from-record bookmark) failure))))
+
+(defun bmkp-default-handler-for-file (filename)
+ "Return a default bookmark handler for FILENAME, or nil.
+If non-nil, it is a Lisp function, determined as follows:
+
+1. Match FILENAME against `bmkp-default-handlers-for-file-types'. If
+it matches a Lisp function, return that function. If it matches a
+shell command, return a Lisp function that invokes that shell command.
+
+2. If no match is found and `bmkp-guess-default-handler-for-file-flag'
+is non-nil, then try to find an appropriate shell command using, in
+order, `dired-guess-default' and `mailcap-file-default-commands'
+\(Emacs 23+ only). If a match is found then return a Lisp function
+that invokes that shell command."
+ (let* ((bmkp-user (bmkp-default-handler-user filename))
+ (shell-cmd (if (stringp bmkp-user)
+ bmkp-user
+ (and (not bmkp-user)
+ bmkp-guess-default-handler-for-file-flag
+ (or (and (require 'dired-x nil t)
+ (let* ((case-fold-search
+ (or (and (boundp 'dired-guess-shell-case-fold-search)
+ dired-guess-shell-case-fold-search)
+ case-fold-search))
+ (default (dired-guess-default (list filename))))
+ (if (consp default) (car default) default)))
+ (and (require 'mailcap nil t) ; Emacs 23+
+ (car (mailcap-file-default-commands (list filename)))))))))
+ (cond ((stringp shell-cmd) `(lambda (bmk) (dired-do-shell-command ',shell-cmd nil ',(list filename))))
+ ((or (functionp bmkp-user) (and bmkp-user (symbolp bmkp-user)))
+ bmkp-user)
+ (t nil))))
+
+(defun bmkp-default-handler-user (filename)
+ "Return default handler for FILENAME.
+The value is based on `bmkp-default-handlers-for-file-types'."
+ (catch 'bmkp-default-handler-user
+ (dolist (assn bmkp-default-handlers-for-file-types)
+ (when (bmkp-string-match-p (car assn) filename) (throw 'bmkp-default-handler-user (cdr assn))))
+ nil))
+
+;; Keep this only for compatibility with existing bookmarks that have `bmkp-sound-jump' as `handler' prop.
+(defun bmkp-sound-jump (bookmark)
+ "Handler for sound files: play the sound file that is BOOKMARK's file.
+This is deprecated. It is kept only for old bookmarks that already
+use this as the `handler' entry. New sound bookmarks use
+`play-sound-file' as entry `file-handler'."
+ (play-sound-file (bookmark-get-filename bookmark)))
+
+(when (> emacs-major-version 21)
+ (defun bmkp-compilation-target-set (&optional prefix) ; Bound to `C-c C-b' in compilation mode
+ "Set a bookmark at the start of the line for this compilation hit.
+The bookmark is set in the indicated file at the indicated line.
+You are prompted for the bookmark name. But with a prefix arg, you
+are prompted only for a PREFIX string. In that case, and in Lisp
+code, the bookmark name is PREFIX followed by the (relative) file name
+of the hit, followed by the line number of the hit."
+ (interactive "P")
+ (let* ((file+line (bmkp-compilation-file+line-at (line-beginning-position)))
+ (file (car file+line))
+ (line (cdr file+line)))
+ (unless (and file line) (error "Cursor is not on a compilation hit"))
+ (save-excursion
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
+ (goto-char (point-min)) (forward-line (1- line))
+ (if (not prefix)
+ (call-interactively #'bookmark-set)
+ (when (interactive-p)
+ (setq prefix (read-string "Prefix for bookmark name: ")))
+ (unless (stringp prefix) (setq prefix ""))
+ (bookmark-set (format "%s%s, line %s" prefix (file-name-nondirectory file) line)
+ 99 'INTERACTIVEP))))))
+
+ (defun bmkp-compilation-file+line-at (&optional pos)
+ "Return the file and position indicated by this compilation message.
+These are returned as a cons: (FILE . POSITION).
+POSITION is the beginning of the line indicated by the message."
+ (unless pos (setq pos (point)))
+ (let* ((loc (car (get-text-property pos 'message)))
+ (line (cadr loc))
+ (filename (caar (nth 2 loc)))
+ (directory (cadr (car (nth 2 loc))))
+ (spec-dir (if directory (expand-file-name directory) default-directory)))
+ (cons (expand-file-name filename spec-dir) line))))
+
+(when (> emacs-major-version 21)
+ (defun bmkp-compilation-target-set-all (prefix &optional msg-p) ; Bound to `C-c C-M-b' in compilation mode
+ "Set a bookmark for each hit of a compilation buffer.
+NOTE: You can use `C-x C-q' to make the buffer writable and then
+ remove any hits that you do not want to bookmark. Only the hits
+ remaining in the buffer are bookmarked.
+
+Interactively, you are prompted for a PREFIX string to prepend to each
+bookmark name, the rest of which is the file name of the hit followed
+by its line number.
+Non-interactively, non-nil optional arg MSG-P means prompt and display
+status messages."
+ (interactive (list (read-string "Prefix for bookmark name: ") 'MSG))
+ (when (and msg-p (not (y-or-n-p "This will bookmark *EACH* hit in the buffer. Continue? ")))
+ (error "OK - canceled"))
+ (let ((count 0))
+ (save-excursion
+ (goto-char (point-min))
+ (when (get-text-property (point) 'message) ; Visible part of buffer starts with a hit
+ (condition-case nil ; because buffer is narrowed or header text otherwise removed.
+ (bmkp-compilation-target-set prefix) ; Ignore error here (e.g. killed buffer).
+ (error nil))
+ (setq count (1+ count)))
+ (while (and (condition-case nil (progn (compilation-next-error 1) t) (error nil))
+ (not (eobp)))
+ (condition-case nil
+ (bmkp-compilation-target-set prefix) ; Ignore error here (e.g. killed buffer).
+ (error nil))
+ (setq count (1+ count)))
+ (when msg-p (message "Set %d bookmarks" count))))))
+
+
+;; We could make the `occur' code work for Emacs 20 & 21 also, but you would not be able to
+;; delete some occurrences and bookmark only the remaining ones.
+
+(when (> emacs-major-version 21)
+ (defun bmkp-occur-target-set (&optional prefix) ; Bound to `C-c C-b' in Occur mode
+ "Set a bookmark at the start of the line for this `(multi-)occur' hit.
+You are prompted for the bookmark name. But with a prefix arg, you
+are prompted only for a PREFIX string. In that case, and in Lisp
+code, the bookmark name is PREFIX followed by the buffer name of the
+hit, followed by the line number of the hit.
+
+You can use this only in `Occur' mode (commands such as `occur' and
+`multi-occur')."
+ (interactive "P")
+ (unless (eq major-mode 'occur-mode) (error "You must be in `occur-mode'"))
+ (let* ((line (and prefix
+ (save-excursion
+ (forward-line 0)
+ ;; We could use [: ] here, to handle `moccur', but that loses anyway for
+ ;; `occur-mode-find-occurrence', so we would need other hoops too.
+ (re-search-forward "^\\s-+\\([0-9]+\\):" (line-end-position) 'NOERROR)
+ (or (format "%5d" (string-to-number (match-string 1))) ""))))
+ (mkr (occur-mode-find-occurrence))
+ (buf (marker-buffer mkr)))
+ (save-excursion (with-current-buffer buf
+ (goto-char mkr)
+ (if (not prefix)
+ (call-interactively #'bookmark-set)
+ (when (interactive-p)
+ (setq prefix (read-string "Prefix for bookmark name: ")))
+ (unless (stringp prefix) (setq prefix ""))
+ (bookmark-set (format "%s%s, line %s" prefix buf line) 99 'INTERACTIVEP)))))))
+
+(when (> emacs-major-version 21)
+ (defun bmkp-occur-target-set-all (&optional prefix msg-p) ; Bound to `C-c C-M-b' in Occur mode
+ "Set a bookmark for each hit of a `(multi-)occur' buffer.
+NOTE: You can use `C-x C-q' to make the buffer writable and then
+ remove any hits that you do not want to bookmark. Only the hits
+ remaining in the buffer are bookmarked.
+
+Interactively, you are prompted for a PREFIX string to prepend to each
+bookmark name, the rest of which is the buffer name of the hit
+followed by its line number.
+
+You can use this only in `Occur' mode (commands such as `occur' and
+`multi-occur').
+
+See also command `bmkp-occur-create-autonamed-bookmarks', which
+creates autonamed bookmarks to all `occur' and `multi-occur' hits.
+
+Non-interactively, non-nil MSG-P means prompt and show status
+messages."
+ (interactive (list (read-string "Prefix for bookmark name: ") 'MSG))
+ (when (and msg-p (not (y-or-n-p "This will bookmark *EACH* hit in the buffer. Continue? ")))
+ (error "OK - canceled"))
+ (let ((count 0))
+ (save-excursion
+ (goto-char (point-min))
+ (while (condition-case nil
+ (progn (occur-next) t) ; "No more matches" ends loop.
+ (error nil))
+ (condition-case nil
+ (bmkp-occur-target-set prefix) ; Ignore error here (e.g. killed buffer).
+ (error nil))
+ (setq count (1+ count)))
+ (when msg-p (message "Set %d bookmarks" count))))))
+
+
+;;(@* "Bookmark Links")
+;; *** Bookmark Links ***
+
+(when (> emacs-major-version 21)
+
+ (defun bmkp-bookmark-linked-at (&optional position msgp)
+ "Return the bookmark linked at POSITION (default: point), or nil if none."
+ (interactive "d\np")
+ (unless position (setq position (point)))
+ (let ((bmk (get-text-property position 'bmkp-bookmark)))
+ (prog1 bmk (when msgp (if bmk (bmkp-describe-bookmark bmk) (message "No bookmark here"))))))
+
+ (defun bmkp-bookmark-linked-at-mouse (event)
+ "Return the bookmark linked at the mouse position."
+ (interactive "e")
+ (bmkp-bookmark-linked-at (posn-point (event-end event)) 'MSG))
+
+ (defun bmkp-jump-to-bookmark-linked-at (&optional position)
+ "Jump to the bookmark linked at POSITION (default: point).
+If a bookmark is linked at POSITION then jump to it. Else raise an error."
+ (interactive "d")
+ (let ((bmk (bmkp-bookmark-linked-at position)))
+ (unless bmk (error "No bookmark here"))
+ (bookmark-jump-other-window bmk)))
+
+ (defun bmkp-jump-to-bookmark-linked-at-mouse (event)
+ "Jump to the bookmark linked at the mouse position."
+ (interactive "e")
+ (bmkp-jump-to-bookmark-linked-at (posn-point (event-end event))))
+
+ (defun bmkp-insert-bookmark-link (bookmark text &optional position)
+ "Put a link to BOOKMARK on the active region or at point.
+You are prompted for the bookmark name.
+If the region is active and nonempty then put the link on its text.
+
+Otherwise, you are prompted for the link text, which is inserted at
+point. The default text for this is the BOOKMARK name. An unlinked
+`SPC' char is inserted after the link, unless it is at the end of a
+line.
+
+Using `?' or double-clicking `mouse-1' on the link describes the
+BOOKMARK. Using `RET' or `mouse-2' on it jumps to BOOKMARK in another
+window.
+
+BOOKMARK is a bookmark name or a bookmark record.
+
+Non-interactively, if the region is inactive or empty then TEXT is the
+link text, and it is inserted at POSITION (point if POSITION is nil)."
+ (interactive
+ (let* ((bmk (bookmark-completing-read "Bookmark"))
+ (txt (if (and transient-mark-mode mark-active (> (region-end) (region-beginning)))
+ (buffer-substring-no-properties (region-end) (region-beginning))
+ (read-string "Insert text: " nil nil bmk))))
+ (list bmk txt)))
+ (with-buffer-modified-unmodified
+ (let* ((regionp (and transient-mark-mode mark-active (> (region-end) (region-beginning))))
+ (beg (if regionp (region-beginning) (or position (point))))
+ (end (and regionp (region-end)))
+ (bmk (bmkp-get-bookmark bookmark))
+ (map (make-sparse-keymap)))
+ (unless bmk (error "No such bookmark"))
+ ;; Use `copy-sequence'. The bookmark name in the bookmark might change.
+ (setq bookmark (copy-sequence (bmkp-bookmark-name-from-record bmk)))
+ (put-text-property 0 (length bookmark) 'bmkp-bookmark bmk bookmark)
+ (define-key map "?" 'bmkp-bookmark-linked-at)
+ (define-key map "\r" 'bmkp-jump-to-bookmark-linked-at)
+ (define-key map [double-mouse-1] 'bmkp-bookmark-linked-at-mouse)
+ (define-key map [mouse-2] 'bmkp-jump-to-bookmark-linked-at-mouse)
+ (define-key map [follow-link] 'mouse-face)
+ (unless regionp (insert text))
+ (add-text-properties beg (or end (point))
+ `(bmkp-bookmark ,bookmark
+ keymap ,map
+ font-lock-ignore t ; Prevent font-lock from changing the face.
+ face link
+ mouse-face highlight
+ help-echo
+ "RET, mouse-2: jump to bookmark; ?, double-mouse-1: describe bookmark"))
+ (unless (or regionp (eolp)) (insert " ")))))
+
+ )
+
+
+;;(@* "Other Bookmark+ Functions (`bmkp-*')")
+;; *** Other Bookmark+ Functions (`bmkp-*') ***
+
+;;;###autoload (autoload 'bmkp-describe-bookmark "bookmark+")
+(defun bmkp-describe-bookmark (bookmark &optional defn) ; Bound to `C-h M'
+ "Describe BOOKMARK.
+With a prefix argument, show the internal definition of the bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'.
+
+Starting with Emacs 22, if the file is an image file then:
+* Show a thumbnail of the image as well.
+* If you have command-line tool `exiftool' installed and in your
+ `$PATH' or `exec-path', then show EXIF data (metadata) about the
+ image. See standard Emacs library `image-dired.el' for more
+ information about `exiftool'"
+ (interactive (list (bookmark-completing-read "Describe bookmark"
+ (or (and (fboundp 'bmkp-default-lighted)
+ (bmkp-default-lighted))
+ (bmkp-default-bookmark-name)))
+ current-prefix-arg))
+ (if defn
+ (bmkp-describe-bookmark-internals bookmark)
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (help-setup-xref (list #'bmkp-describe-bookmark bookmark) (interactive-p))
+ (let ((help-text (bmkp-bookmark-description bookmark)))
+ (bmkp-with-help-window "*Help*" (princ help-text) (bmkp-add-jump-to-list-button bookmark))
+ (with-current-buffer "*Help*"
+ (save-excursion
+ (goto-char (point-min))
+ (when (re-search-forward "@#%&()_IMAGE-HERE_()&%#@\\(.+\\)" nil t)
+ (let* ((image-file (match-string 1))
+ (image-string (save-match-data
+ (apply #'propertize "X"
+ `(display
+ ,(append (image-dired-get-thumbnail-image image-file)
+ '(:margin 10))
+ rear-nonsticky (display)
+ mouse-face highlight
+ follow-link t
+ help-echo "`mouse-2' or `RET': Show full image"
+ keymap
+ (keymap
+ (mouse-2
+ . (lambda (e) (interactive "e")
+ (find-file ,image-file)))
+ (13
+ . (lambda () (interactive)
+ (find-file ,image-file))))))))
+ (buffer-read-only nil))
+ (replace-match image-string)))))
+ help-text)))
+
+(defun bmkp-bookmark-description (bookmark &optional no-image)
+ "Help-text description of BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'.
+
+Starting with Emacs 22 and unless optional arg NO-IMAGE is non-nil, if
+the file is an image file then the description includes the following:
+* A placeholder for a thumbnail image: \"@#%&()_IMAGE-HERE_()&%#@\"
+* EXIF data (metadata) about the image, provided you have command-line
+ tool `exiftool' installed and in your `$PATH' or `exec-path'. See
+ standard Emacs library `image-dired.el' for more information about
+ `exiftool'."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (let ((print-circle bmkp-propertize-bookmark-names-flag) ; For `pp-to-string'
+ (print-gensym bmkp-propertize-bookmark-names-flag) ; For `pp-to-string'
+ (print-length nil) ; For `pp-to-string'
+ (print-level nil) ; For `pp-to-string'
+ (bname (bmkp-bookmark-name-from-record bookmark))
+ (buf (bmkp-get-buffer-name bookmark))
+ (file (bookmark-get-filename bookmark))
+ (image-p (bmkp-image-bookmark-p bookmark))
+ (location (bookmark-prop-get bookmark 'location))
+ (start (bookmark-get-position bookmark))
+ (end (bmkp-get-end-position bookmark))
+ (created (bookmark-prop-get bookmark 'created))
+ (time (bmkp-get-visit-time bookmark))
+ (visits (bmkp-get-visits-count bookmark))
+ (tags (mapcar #'bmkp-tag-name (bmkp-get-tags bookmark)))
+ (sequence-p (bmkp-sequence-bookmark-p bookmark))
+ (function-p (bmkp-function-bookmark-p bookmark))
+ (kmacro-p (bmkp-kmacro-list-bookmark-p bookmark))
+ (variable-list-p (bmkp-variable-list-bookmark-p bookmark))
+ (search-hits-p (bmkp-icicles-search-hits-bookmark-p bookmark))
+ (non-invokable-p (bmkp-non-invokable-bookmark-p bookmark))
+ (desktop-p (bmkp-desktop-bookmark-p bookmark))
+ (bookmark-file-p (bmkp-bookmark-file-bookmark-p bookmark))
+ (snippet-p (bmkp-snippet-bookmark-p bookmark))
+ (dired-p (bmkp-dired-bookmark-p bookmark))
+ (gnus-p (bmkp-gnus-bookmark-p bookmark))
+ (info-p (bmkp-info-bookmark-p bookmark))
+ (man-p (bmkp-man-bookmark-p bookmark))
+ (url-p (bmkp-url-bookmark-p bookmark))
+ (eww-p (and (fboundp 'bmkp-eww-bookmark-p) (bmkp-eww-bookmark-p bookmark))) ; Emacs 25+
+ (w3m-p (bmkp-w3m-bookmark-p bookmark))
+ (temp-p (bmkp-temporary-bookmark-p bookmark))
+ (annot (bookmark-get-annotation bookmark))
+ non-file-p no-position-p)
+ (setq non-file-p (equal file bmkp-non-file-filename)
+ no-position-p (not start))
+ (when (or sequence-p function-p variable-list-p kmacro-p search-hits-p) (setq no-position-p t))
+ (let* ((temp-text (if temp-p "TEMPORARY " ""))
+ (help-text
+ (concat
+ (format "%sBookmark `%s'\n%s\n\n" temp-text bname
+ (make-string (+ 11 (length temp-text) (length bname)) ?-))
+ (cond (sequence-p (concat "Sequence:\n\t"
+ (mapconcat (lambda (bname)
+ (let ((name (copy-sequence bname)))
+ (set-text-properties 0 (length name) () name)
+ name))
+ (bookmark-prop-get bookmark 'sequence)
+ "\n\t")
+ "\n"))
+ (function-p (let ((fn (bookmark-prop-get bookmark 'function)))
+ (if (symbolp fn)
+ (format "Function:\t\t%s\n" fn)
+ (format "Function:\n%s\n"
+ (pp-to-string (bookmark-prop-get bookmark 'function))))))
+ (kmacro-p (format "Keyboard Macro List (MACRO COUNT COUNT-FORMAT):\n\n%s\n"
+ (pp-to-string (bookmark-prop-get bookmark 'kmacros))))
+ (variable-list-p (format "Variable list:\n%s\n"
+ (pp-to-string (bookmark-prop-get bookmark 'variables))))
+ (search-hits-p (format "Icicles search hits:\n%s\n\n"
+ (mapconcat (lambda (hit)
+ (let ((hit-copy (copy-sequence hit)))
+ (set-text-properties 0 (length hit-copy) ()
+ hit-copy)
+ hit-copy))
+ (bookmark-prop-get bookmark 'hits)
+ "\n\t")))
+ (non-invokable-p (format "Non-invokable:\n\n%s"
+ (let ((desc (bookmark-prop-get bookmark 'filter-description)))
+ (if desc
+ (format "Isearch filter:\n%s\n" desc)
+ ""))))
+ (gnus-p (format "Gnus, group:\t\t%s, article: %s, message-id: %s\n"
+ (bookmark-prop-get bookmark 'group)
+ (bookmark-prop-get bookmark 'article)
+ (bookmark-prop-get bookmark 'message-id)))
+ (man-p (format "UNIX `man' page for:\t`%s'\n"
+ (or (bookmark-prop-get bookmark 'man-args)
+ ;; WoMan has no variable for the cmd name.
+ (bookmark-prop-get bookmark 'buffer-name))))
+ (info-p (and file (format "Info node:\t\t(%s) %s\n"
+ (file-name-nondirectory file)
+ (bookmark-prop-get bookmark 'info-node))))
+ (eww-p (and file (format "EWW URL:\t\t%s\n" file))) ; Emacs 25+
+ (w3m-p (and file (format "W3m URL:\t\t%s\n" file)))
+ (url-p (format "URL:\t\t\t%s\n" location))
+ (desktop-p (format "Desktop file:\t\t%s\n"
+ (bookmark-prop-get bookmark 'desktop-file)))
+ (bookmark-file-p (format "Bookmark file:\t\t%s\n"
+ (bookmark-prop-get bookmark 'bookmark-file)))
+ (snippet-p (format "Snippet for `kill-ring'.\n"))
+ (dired-p (and file
+ (let ((switches (bookmark-prop-get bookmark 'dired-switches))
+ (marked (length (bookmark-prop-get bookmark
+ 'dired-marked)))
+ (inserted (length (bookmark-prop-get bookmark
+ 'dired-subdirs)))
+ (hidden (length (bookmark-prop-get bookmark
+ 'dired-hidden-dirs))))
+ (format "Dired%s:%s\t\t%s\nMarked:\t\t\t%s\n\
+Inserted subdirs:\t%s\nHidden subdirs:\t\t%s\n"
+ (if switches (format " `%s'" switches) "")
+ (if switches "" (format "\t"))
+ (expand-file-name file)
+ marked inserted hidden))))
+ (non-file-p (or (and location (format "Location:\t\t%s\n" location))
+ (and buf (format "Buffer:\t\t\t%s\n" buf))))
+ (file (concat (format "File:\t\t\t%s\n" (file-name-nondirectory file))
+ (let ((dir (file-name-directory (expand-file-name file))))
+ (and dir (format "Directory:\t\t%s\n" dir)))))
+ (t "Unknown\n"))
+ (unless no-position-p
+ (if (bmkp-region-bookmark-p bookmark)
+ (format "Region:\t\t\t%d to %d (%d chars)\n" start end (- end start))
+ (format "Position:\t\t%d\n" start)))
+ (and visits (format "Visits:\t\t\t%d\n" visits))
+ (and time (format "Last visit:\t\t%s\n" (format-time-string "%c" time)))
+ (and created (format "Creation:\t\t%s\n" (format-time-string "%c" created)))
+ (and tags (format "Tags:\n \"%s\"\n" (mapconcat #'identity tags "\"\n \"")))
+ (and annot (format "\nAnnotation:\n%s\n" annot))
+ (and snippet-p (format "\nSnippet:\n%s\n" (bookmark-prop-get bookmark 'text)))
+ (and (not no-image)
+ file
+ (fboundp 'image-file-name-regexp) ; In `image-file.el' (Emacs 22+).
+ (bmkp-string-match-p (image-file-name-regexp) file)
+ (if (fboundp 'display-graphic-p) (display-graphic-p) window-system)
+ (require 'image-dired nil t)
+ (image-dired-get-thumbnail-image file)
+ (concat "\n@#%&()_IMAGE-HERE_()&%#@" file "\n"))
+ (and (not no-image)
+ file
+ (fboundp 'image-file-name-regexp) ; In `image-file.el' (Emacs 22+).
+ (bmkp-string-match-p (image-file-name-regexp) file)
+ (progn (message "Gathering image data...") t)
+ (condition-case nil
+ (let ((all (bmkp-all-exif-data (expand-file-name file))))
+ (concat
+ (and all (not (zerop (length all)))
+ (format "\nImage Data (EXIF)\n-----------------\n%s"
+ all))))
+ (error nil))))))
+ help-text)))
+
+(when (and (> emacs-major-version 21)
+ (condition-case nil (require 'help-mode nil t) (error nil))
+ (get 'help-xref 'button-category-symbol)) ; In `button.el'
+ (define-button-type 'bmkp-jump-to-list-button
+ :supertype 'help-xref
+ 'help-function #'bmkp-jump-to-list
+ 'help-echo
+ (purecopy "mouse-2, RET: Show in `*Bookmark List*'")))
+
+(defun bmkp-add-jump-to-list-button (bookmark)
+ "Add a [Show in `*Bookmark List*'] button for BOOKMARK."
+ (with-current-buffer "*Help*"
+ (let ((buffer-read-only nil))
+ ;; Add button to go to the bookmark entry in `*Bookmark List*'.
+ ;; Not for Emacs 21.3 - its `help-insert-xref-button' signature is different.
+ (when (and (> emacs-major-version 21) ; In `help-mode.el'.
+ (condition-case nil (require 'help-mode nil t) (error nil))
+ (fboundp 'help-insert-xref-button))
+ (goto-char (point-min)) (forward-line 2)
+ (help-insert-xref-button "[Show in `*Bookmark List*']"
+ #'bmkp-jump-to-list-button
+ (bookmark-name-from-record bookmark))
+ (insert "\n")))))
+
+;; This is the same as `help-all-exif-data' in `help-fns+.el', but we avoid requiring that library.
+(defun bmkp-all-exif-data (file)
+ "Return all EXIF data from FILE, using command-line tool `exiftool'."
+ (with-temp-buffer
+ (delete-region (point-min) (point-max))
+ (unless (eq 0 (call-process shell-file-name nil t nil shell-command-switch
+ (format "exiftool -All \"%s\"" file)))
+ (error "Could not get EXIF data"))
+ (buffer-string)))
+
+
+;;;###autoload (autoload 'bmkp-describe-bookmark-internals "bookmark+")
+(defun bmkp-describe-bookmark-internals (bookmark)
+ "Show the internal definition of the bookmark BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+If it is a record then it need not belong to `bookmark-alist'."
+ (interactive (list (bookmark-completing-read "Describe bookmark" (bmkp-default-bookmark-name))))
+ ;; Work with a copy of the bookmark, so we can unpropertize the name.
+ (setq bookmark (copy-sequence (bmkp-get-bookmark bookmark)))
+ (help-setup-xref (list #'bmkp-describe-bookmark-internals bookmark) (interactive-p))
+ (let* ((bname (copy-sequence (bmkp-bookmark-name-from-record bookmark)))
+ (IGNORE (set-text-properties 0 (length bname) nil bname)) ; Strip properties from name.
+ (bmk (cons bname (bmkp-bookmark-data-from-record bookmark))) ; Fake bmk with stripped name.
+ (print-circle bmkp-propertize-bookmark-names-flag) ; For `pp-to-string'
+ (print-gensym bmkp-propertize-bookmark-names-flag) ; For `pp-to-string'
+ (print-length nil) ; For `pp-to-string'
+ (print-level nil) ; For `pp-to-string'
+ (help-text (format "Bookmark `%s'\n%s\n\n%s" bname (make-string (+ 11 (length bname)) ?-)
+ (pp-to-string bmk))))
+ (bmkp-with-help-window "*Help*" (princ help-text))
+ (bmkp-add-jump-to-list-button bookmark)
+ help-text))
+
+(defun bmkp-annotation-or-bookmark-description (bookmark)
+ "Return the annotation or description of BOOKMARK as a string.
+If BOOKMARK has an annotation then use that; else the description."
+ (or (bookmark-get-annotation bookmark)
+ (bmkp-bookmark-description bookmark)))
+
+;;;###autoload (autoload 'bmkp-list-defuns-in-commands-file "bookmark+")
+(defun bmkp-list-defuns-in-commands-file ()
+ "List the functions defined in `bmkp-bmenu-commands-file'.
+Typically, these are all commands."
+ (interactive)
+ (when (and bmkp-bmenu-commands-file (file-readable-p bmkp-bmenu-commands-file))
+ (when (file-directory-p bmkp-bmenu-commands-file)
+ (error "`%s' is a directory, not a file" bmkp-bmenu-commands-file))
+ (let ((fns ())
+ (buf (let ((enable-local-variables nil))
+ (find-file-noselect bmkp-bmenu-commands-file))))
+ (help-setup-xref (list #'bmkp-list-defuns-in-commands-file) (interactive-p))
+ (with-current-buffer buf
+ (goto-char (point-min))
+ (while (not (eobp))
+ (when (re-search-forward "\\s-*(defun \\([^ \t\n(\"]+\\)[ \t\n(]" nil 'move)
+ (push (match-string 1) fns)))
+ (setq fns (nreverse fns)
+ fns (sort fns 'string-lessp)))
+ (when (buffer-live-p buf) (kill-buffer buf))
+ (bmkp-with-help-window "*Help*"
+ (princ "Bookmark Commands You Defined (in `bmkp-bmenu-commands-file')") (terpri)
+ (princ "------------------------------------------------------------------") (terpri)
+ (terpri)
+ (let ((non-dups (bmkp-remove-dups fns)))
+ (dolist (fn non-dups)
+ (if (and (fboundp (intern fn)) (fboundp 'help-insert-xref-button))
+ (with-current-buffer "*Help*"
+ (goto-char (point-max))
+ (help-insert-xref-button fn 'help-function (intern fn) (commandp (intern fn))))
+ (princ fn))
+ (let ((dups (member fn fns)) ; Sorted, so all dups are together.
+ (count 0))
+ (while (equal fn (car dups))
+ (setq count (1+ count)
+ dups (cdr dups)))
+ (when (> count 1) (princ (format " (%d times)" count))))
+ (terpri)))
+ (help-make-xrefs (current-buffer)))
+ fns)))
+
+(defun bmkp-root-or-sudo-logged-p ()
+ "Return t if the user logged in using Tramp as `root' or `sudo'.
+Otherwise, return nil."
+ (catch 'break
+ (dolist (ii (mapcar #'buffer-name (buffer-list)))
+ (when (bmkp-string-match-p "*tramp/\\(su\\|sudo\\) ." ii) (throw 'break t)))))
+
+(defun bmkp-position-post-context (breg)
+ "Return `bookmark-search-size' chars, starting at position BREG.
+Return nil if there are not that many chars.
+This is text that follows the bookmark's `position'.
+This is used for a non-region bookmark."
+ (and (>= (- (point-max) breg) bookmark-search-size)
+ (buffer-substring-no-properties breg (+ breg bookmark-search-size))))
+
+(defun bmkp-position-post-context-region (breg ereg)
+ "Return the region prefix, at BREG.
+Return at most `bmkp-region-search-size' or (- EREG BREG) chars.
+This is text that follows the bookmark's `position'.
+This is used for a region bookmark."
+ (buffer-substring-no-properties breg (+ breg (min bmkp-region-search-size (- ereg breg)))))
+
+(defun bmkp-position-pre-context (breg)
+ "Return `bookmark-search-size' chars that precede BREG.
+Return nil if there are not that many chars.
+This is text that precedes the bookmark's `position'.
+This is used for a non-region bookmark."
+ (and (>= (- breg (point-min)) bookmark-search-size)
+ (buffer-substring-no-properties breg (- breg bookmark-search-size))))
+
+(defun bmkp-position-pre-context-region (breg)
+ "Return the text preceding the region beginning, BREG.
+Return at most `bmkp-region-search-size' chars.
+This is text that precedes the bookmark's `position'.
+This is used for a region bookmark."
+ (buffer-substring-no-properties (max (- breg bmkp-region-search-size) (point-min)) breg))
+
+(defun bmkp-end-position-pre-context (breg ereg)
+ "Return the region suffix, ending at EREG.
+Return at most `bmkp-region-search-size' or (- EREG BREG) chars.
+This is text that precedes the bookmark's `end-position'."
+ (buffer-substring-no-properties (- ereg (min bmkp-region-search-size (- ereg breg))) ereg))
+
+(defun bmkp-end-position-post-context (ereg)
+ "Return the text following the region end, EREG.
+Return at most `bmkp-region-search-size' chars.
+This is text that follows the bookmark's `end-position'."
+ (buffer-substring-no-properties ereg (+ ereg (min bmkp-region-search-size (- (point-max) ereg)))))
+
+(defun bmkp-position-after-whitespace (position)
+ "Move forward from POSITION, skipping over whitespace. Return point."
+ (goto-char position) (skip-chars-forward " \n\t" (point-max)) (point))
+
+(defun bmkp-position-before-whitespace (position)
+ "Move backward from POSITION, skipping over whitespace. Return point."
+ (goto-char position) (skip-chars-backward " \n\t" (point-min)) (point))
+
+(defun bmkp-save-new-region-location (bookmark beg end)
+ "Update and save `bookmark-alist' for BOOKMARK, relocating its region.
+Saving happens according to `bookmark-save-flag'.
+BOOKMARK is a bookmark record.
+BEG and END are the new region limits for BOOKMARK.
+Do nothing and return nil if `bmkp-save-new-location-flag' is nil.
+Otherwise, return non-nil if region was relocated."
+ (and bmkp-save-new-location-flag
+ (y-or-n-p "Region relocated. Do you want to save new region limits? ")
+ (progn
+ (bookmark-prop-set bookmark 'front-context-string (bmkp-position-post-context-region beg end))
+ (bookmark-prop-set bookmark 'rear-context-string (bmkp-position-pre-context-region beg))
+ (bookmark-prop-set bookmark 'front-context-region-string (bmkp-end-position-pre-context beg end))
+ (bookmark-prop-set bookmark 'rear-context-region-string (bmkp-end-position-post-context end))
+ (bookmark-prop-set bookmark 'position beg)
+ (bookmark-prop-set bookmark 'end-position end)
+ (bmkp-maybe-save-bookmarks)
+ t)))
+
+(defun bmkp-handle-region-default (bookmark)
+ "Default function to handle BOOKMARK's region.
+BOOKMARK is a bookmark name or a bookmark record.
+Relocate the region if necessary, then activate it.
+If region was relocated, save it if user confirms saving."
+ ;; Relocate by searching from the beginning (and possibly the end) of the buffer.
+ (let* (;; Get bookmark object once and for all.
+ ;; We should know BOOKMARK is a bookmark record (not a name), but play it safe.
+ (bmk (bmkp-get-bookmark bookmark))
+ (bor-str (bookmark-get-front-context-string bmk))
+ (eor-str (bookmark-prop-get bmk 'front-context-region-string))
+ (br-str (bookmark-get-rear-context-string bmk))
+ (ar-str (bookmark-prop-get bookmark 'rear-context-region-string))
+ (pos (bookmark-get-position bmk))
+ (end-pos (bmkp-get-end-position bmk))
+ (reg-retrieved-p t)
+ (reg-relocated-p nil))
+ (unless (and end-pos
+ (string= bor-str (buffer-substring-no-properties
+ (point) (min (point-max) (+ (point) (length bor-str)))))
+ (string= eor-str (buffer-substring-no-properties
+ end-pos (max (point-min) (- end-pos (length bor-str))))))
+ ;; Relocate region by searching from beginning (and possibly from end) of buffer.
+ (let ((beg nil)
+ (end nil))
+ ;; Go to bob and search forward for END.
+ (goto-char (point-min))
+ (if (search-forward eor-str (point-max) t) ; Find END, using `eor-str'.
+ (setq end (point))
+ ;; Verify that region is not before context.
+ (unless (search-forward br-str (point-max) t)
+ (when (search-forward ar-str (point-max) t) ; Find END, using `ar-str'.
+ (setq end (match-beginning 0)
+ end (and end (bmkp-position-before-whitespace end))))))
+ ;; If failed to find END, go to eob and search backward for BEG.
+ (unless end (goto-char (point-max)))
+ (if (search-backward bor-str (point-min) t) ; Find BEG, using `bor-str'.
+ (setq beg (point))
+ ;; Verify that region is not after context.
+ (unless (search-backward ar-str (point-min) t)
+ (when (search-backward br-str (point-min) t) ; Find BEG, using `br-str'.
+ (setq beg (match-end 0)
+ beg (and beg (bmkp-position-after-whitespace beg))))))
+ (setq reg-retrieved-p (or beg end)
+ reg-relocated-p reg-retrieved-p
+ ;; If only one of BEG or END was found, the relocated region is only
+ ;; approximate (keep the same length). If both were found, it is exact.
+ pos (or beg (and end pos end-pos (- end (- end-pos pos))) pos)
+ end-pos (or end (and beg pos end-pos (+ pos (- end-pos pos))) end-pos))))
+ ;; Region is available. Activate it and maybe save it.
+ (cond (reg-retrieved-p
+ (when pos (goto-char pos))
+ (when end-pos (push-mark end-pos 'nomsg 'activate))
+ (when bmkp-show-end-of-region-flag
+ (let ((end-win (save-excursion (forward-line (window-height)) (line-end-position))))
+ ;; Bounce point and mark.
+ (save-excursion (sit-for 0.6) (exchange-point-and-mark) (sit-for 1))
+ ;; Recenter if region end is not visible.
+ (when (and end-pos (> end-pos end-win)) (recenter 1))))
+ ;; Maybe save region.
+ (if (and reg-relocated-p (bmkp-save-new-region-location bmk pos end-pos))
+ (message "Saved relocated region%s" (if (and pos end-pos)
+ (format " (from %d to %d)" pos end-pos)
+ ""))
+ (when (and pos end-pos) (message "Region is from %d to %d" pos end-pos)))
+ (when (and pos end-pos)
+ (goto-char pos)
+ (push-mark end-pos 'nomsg 'activate)
+ (setq deactivate-mark nil)))
+ ((and pos end-pos) ; No region. Go to old start. Don't push-mark.
+ (goto-char pos) (forward-line 0)
+ (message "No region from %d to %d" pos end-pos)))))
+
+(defun bmkp-goto-position (bookmark file buf bufname pos forward-str behind-str)
+ "Go to a bookmark that has no region.
+Update the recorded position if POS and `bmkp-save-new-location-flag'
+are non-nil.
+
+Arguments are respectively the bookmark, its file, buffer, buffer
+name, recorded position, and the context strings for the position."
+ (if (and file (file-readable-p file) (not (buffer-live-p buf)))
+;;; $$$$$$$ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
+ (with-current-buffer (find-file-noselect file) (setq buf (buffer-name)))
+ ;; No file found. See if a non-file buffer exists for this. If not, raise error.
+ (unless (or (and buf (get-buffer buf))
+ (and bufname (get-buffer bufname) (not (string= buf bufname))))
+ (signal 'file-error `("Jumping to bookmark" ,(format "Cannot access file `%s' or buffer `%s'"
+ file bufname)))))
+ (set-buffer (or buf bufname))
+ (when bmkp-jump-display-function
+ (save-current-buffer (funcall bmkp-jump-display-function (current-buffer))))
+ (setq deactivate-mark t)
+ (raise-frame)
+ (when pos (goto-char pos))
+ ;; Try to relocate position.
+ ;; Search forward first. Then, if FORWARD-STR exists and was found in the file, search
+ ;; backward for BEHIND-STR. The rationale is that if text was inserted between the two
+ ;; in the file, then it's better to end up before point, so you can see the text, rather
+ ;; than after it and not see it.
+ (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)))
+ (when (and (not (equal pos (point))) bmkp-save-new-location-flag)
+ (bookmark-prop-set bookmark 'position (point))
+ (bookmark-prop-set bookmark 'end-position (point))
+ ;; Perhaps we should treat the case of a bookmark that had position 0 changing to position 1 specially,
+ ;; by passing non-nil SAME-COUNT-P arg to `bmkp-maybe-save-bookmarks'. On the other hand, if initially
+ ;; 0 then the bookmark does not claim that the file is non-empty. If now set to 1 then we know it is.
+ ;; Leave it this way, at least for now. The consequence is that the user will see that bookmarks have
+ ;; modified (e.g. `Save' is enabled in the menu), even though nothing much has changed.
+ (bmkp-maybe-save-bookmarks))
+ (not (equal pos (point)))) ; Return value indicates whether POS was accurate.
+
+(defun bmkp-jump-sequence (bookmark)
+ "Handle a sequence bookmark BOOKMARK.
+Handler function for sequence bookmarks.
+BOOKMARK is a bookmark name or a bookmark record."
+ (dolist (bmk (bookmark-prop-get bookmark 'sequence))
+ (bookmark--jump-via bmk bmkp-sequence-jump-display-function))
+ (message "Done invoking bookmarks in sequence `%s'"
+ (if (stringp bookmark) bookmark (bmkp-bookmark-name-from-record bookmark))))
+
+(defun bmkp-jump-function (bookmark)
+ "Handle a function bookmark BOOKMARK.
+Handler function for function bookmarks.
+BOOKMARK is a bookmark name or a bookmark record."
+ (let ((fn (bookmark-prop-get bookmark 'function)))
+ (cond ((functionp fn) (funcall fn))
+ ((vectorp fn)
+ (execute-kbd-macro fn current-prefix-arg)))))
+
+(defun bmkp-make-bookmark-list-record ()
+ "Create and return a bookmark-list bookmark record.
+This records the current state of buffer `*Bookmark List*': the sort
+order, filter function, regexp pattern, title, and omit list."
+ (let ((state `((last-sort-comparer . ,bmkp-sort-comparer)
+ (last-reverse-sort-p . ,bmkp-reverse-sort-p)
+ (last-reverse-multi-sort-p . ,bmkp-reverse-multi-sort-p)
+ (last-bmenu-filter-function . ,bmkp-bmenu-filter-function)
+ (last-bmenu-filter-pattern . ,bmkp-bmenu-filter-pattern)
+ (last-bmenu-omitted-bookmarks . ,(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-omitted-bookmarks))
+ (last-bmenu-title . ,bmkp-bmenu-title)
+ (last-bmenu-toggle-filenames . ,bookmark-bmenu-toggle-filenames))))
+ `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT)
+ (filename . ,bmkp-non-file-filename)
+ (bookmark-list . ,state)
+ (handler . bmkp-jump-bookmark-list))))
+
+(add-hook 'bookmark-bmenu-mode-hook
+ (lambda () (set (make-local-variable 'bookmark-make-record-function)
+ 'bmkp-make-bookmark-list-record)))
+
+(defun bmkp-jump-bookmark-list (bookmark)
+ "Jump to bookmark-list bookmark BOOKMARK.
+Handler function for record returned by
+`bmkp-make-bookmark-list-record'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (let ((state (bookmark-prop-get bookmark 'bookmark-list)))
+ (setq bmkp-sort-comparer (cdr (assq 'last-sort-comparer state))
+ bmkp-reverse-sort-p (cdr (assq 'last-reverse-sort-p state))
+ bmkp-reverse-multi-sort-p (cdr (assq 'last-reverse-multi-sort-p state))
+ bmkp-bmenu-filter-function (cdr (assq 'last-bmenu-filter-function state))
+ bmkp-bmenu-filter-pattern (or (cdr (assq 'last-bmenu-filter-pattern state)) "")
+ bmkp-bmenu-omitted-bookmarks (cdr (assq 'last-bmenu-omitted-bookmarks state))
+ bmkp-bmenu-title (cdr (assq 'last-bmenu-title state))
+ bookmark-bmenu-toggle-filenames (cdr (assq 'last-bmenu-toggle-filenames state))))
+ (let ((bookmark-alist (if bmkp-bmenu-filter-function
+ (funcall bmkp-bmenu-filter-function)
+ bookmark-alist)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp)
+ (when (get-buffer bmkp-bmenu-buffer) (pop-to-buffer bmkp-bmenu-buffer))))
+
+;; Bookmark-file bookmarks.
+;;;###autoload (autoload 'bmkp-set-bookmark-file-bookmark "bookmark+")
+(defun bmkp-set-bookmark-file-bookmark (file &optional msg-p) ; Bound to `C-x x y', `C-x x c y'
+ "Create a bookmark that loads bookmark-file FILE when \"jumped\" to.
+You are prompted for the names of the bookmark file and the bookmark.
+When entering the bookmark name you can use completion against
+existing names. This completion is lax, so you can easily edit an
+existing name. See `bookmark-set' for particular keys available
+during this input.
+
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive
+ (list (let* ((insert-default-directory t)
+ (std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ bookmark-default-file
+ std-default)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Create bookmark to load bookmark file: "
+ (or (file-name-directory default) "~/")
+ default
+ 'confirm)) ; Non-existing file is OK, but must confirm.
+ 'MSG))
+ (setq file (expand-file-name file))
+ (when (file-directory-p file) (error "`%s' is a directory, not a file" file))
+ (unless (file-readable-p file) (error "Unreadable bookmark file `%s'" file))
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
+ (goto-char (point-min))
+ (condition-case nil ; Check whether it's a valid bookmark file.
+ (progn (bookmark-maybe-upgrade-file-format)
+ (unless (listp (bookmark-alist-from-buffer)) (error "")))
+ (error (error "Not a valid bookmark file: `%s'" file))))
+ (let ((bookmark-make-record-function (lexical-let ((ff file))
+ (lambda () (bmkp-make-bookmark-file-record ff))))
+ (bookmark-name (bmkp-completing-read-lax "Bookmark-file BOOKMARK name"
+ file nil nil 'bookmark-history)))
+ (bookmark-set bookmark-name 99 'INTERACTIVEP))
+ (when msg-p (message "Set bookmark-file bookmark")))
+
+(defun bmkp-make-bookmark-file-record (bookmark-file)
+ "Create and return a bookmark-file bookmark record.
+Records the BOOKMARK-FILE name.
+Adds a handler that tests the prefix arg and loads the bookmark file
+either as a replacement for the current bookmark file or as a
+supplement to it."
+ `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT nil nil 'NO-REGION)
+ (filename . ,bookmark-file)
+ (bookmark-file . ,bookmark-file)
+ (handler . bmkp-jump-bookmark-file)))
+
+(defun bmkp-jump-bookmark-file (bookmark &optional switchp batchp)
+ "Jump to bookmark-file bookmark BOOKMARK, which loads the bookmark file.
+Handler function for record returned by
+`bmkp-make-bookmark-file-record'.
+BOOKMARK is a bookmark name or a bookmark record.
+Non-nil optional arg SWITCHP means overwrite current bookmark list.
+Non-nil optional arg BATCHP is passed to `bookmark-load'."
+ (let ((file (bookmark-prop-get bookmark 'bookmark-file))
+ (overwritep (and switchp (y-or-n-p "SWITCH to new bookmark file, instead of just adding it? "))))
+ (bookmark-load file overwritep batchp)) ; Treat load interactively, if no BATCHP.
+ ;; This `throw' is only for the case where this handler is called from `bookmark--jump-via'.
+ ;; It just tells `bookmark--jump-via' to skip the rest of what it does after calling the handler.
+ (condition-case nil
+ (throw 'bookmark--jump-via 'BOOKMARK-FILE-JUMP)
+ (no-catch nil)))
+
+;;;###autoload (autoload 'bmkp-bookmark-file-jump "bookmark+")
+(defun bmkp-bookmark-file-jump (bookmark &optional switchp no-msg) ; `C-x j y'
+ "Jump to a bookmark-file bookmark, which means load its bookmark file.
+With a prefix argument, switch to the new bookmark file.
+Otherwise, load it to supplement the current bookmark list.
+BOOKMARK is a bookmark name or a bookmark record."
+ (interactive
+ (let ((alist (bmkp-bookmark-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "bookmark-file" alist nil nil 'bmkp-bookmark-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-bookmark-file-alist-only))))
+ (bmkp-jump-bookmark-file bookmark switchp no-msg))
+
+;;;###autoload (autoload 'bmkp-bookmark-file-load-jump "bookmark+")
+(defun bmkp-bookmark-file-load-jump (bookmark &optional nosavep)
+ "Prompt for a bookmark-file BOOKMARK and load that file's bookmarks.
+This adds to the current bookmark list. It does not overwrite it.
+By default, this first saves the current bookmark list in the current
+bookmark file. With a prefix argument it does not save first.
+BOOKMARK is a bookmark name or a bookmark record."
+ (interactive
+ (let ((alist (bmkp-bookmark-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "bookmark-file" alist nil nil 'bmkp-bookmark-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-bookmark-file-alist-only))))
+ (let ((file (bookmark-prop-get bookmark 'bookmark-file)))
+ (bookmark-load file nil (if nosavep t 'save))
+ (bmkp-refresh/rebuild-menu-list)
+ (message "Added bookmarks in `%s'" file)))
+
+;;;###autoload (autoload 'bmkp-bookmark-file-switch-jump "bookmark+")
+(defun bmkp-bookmark-file-switch-jump (bookmark &optional nosavep)
+ "Prompt for a bookmark-file BOOKMARK and switch to that bookmark file.
+Unlike `C-u \\[bmkp-bookmark-file-jump]', you are not prompted for confirmation.
+By default, this first saves the current bookmark list in the current
+bookmark file. With a prefix argument it does not save first.
+BOOKMARK is a bookmark name or a bookmark record."
+ (interactive
+ (let ((alist (bmkp-bookmark-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "bookmark-file" alist nil nil 'bmkp-bookmark-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-bookmark-file-alist-only))))
+ (let ((file (bookmark-prop-get bookmark 'bookmark-file)))
+ (bookmark-load file t (if nosavep t 'save))
+ (bmkp-refresh/rebuild-menu-list)
+ (message "Switched to bookmarks in `%s'" file)))
+
+
+;; Snippet bookmarks
+;; Inspired by emacs-develNOSPAMgnu.org post from Masatake Yamato [yamatoNOSPAMredhat.com], 2012-01-06.
+;;;###autoload (autoload 'bmkp-set-snippet-bookmark "bookmark+")
+(defun bmkp-set-snippet-bookmark (beg end &optional promptp msgp)
+ ; Bound globally to `C-x x c M-w'.
+ "Save the text of the active region as a bookmark.
+The bookmark is automatically named with the first line of the region
+text. With a prefix argument you are prompted for the name instead.
+
+Jumping to the bookmark copies the saved text to the `kill-ring', so
+you can yank it using `C-y'."
+ (interactive "r\nP\np")
+ (unless (and mark-active transient-mark-mode) (error "No active region"))
+ (when (equal beg end) (error "Region is empty"))
+ (lexical-let ((text (buffer-substring-no-properties beg end)))
+ (let ((bookmark-make-record-function (lambda ()
+ `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT)
+ (text . ,text)
+ (handler . bmkp-jump-snippet))))
+ (bname (and (not promptp) (car (split-string text "[\n]")))))
+ (bookmark-set bname 99 'INTERACTIVEP)
+ ;; `bookmark-set does the prompting, providing default names.
+ (when msgp (message "Region text bookmarked%s" (if bname (format " as `%s'" bname) ""))))))
+
+(defun bmkp-jump-snippet (bookmark)
+ "Copy the text saved in BOOKMARK to the `kill-ring'.
+Handler for snippet bookmarks."
+ (kill-new (bookmark-prop-get bookmark 'text))
+ (message "Snippet of bookmark `%s' copied to `kill-ring'" (bmkp-bookmark-name-from-record bookmark)))
+
+;;;###autoload (autoload 'bmkp-snippet-to-kill-ring "bookmark+")
+(defun bmkp-snippet-to-kill-ring (bookmark) ; `C-x j M-w'
+ "Jump to a snippet bookmark: copy its saved text to the `kill-ring'.
+This is a specialization of `bookmark-jump' for snippet bookmarks."
+ (interactive
+ (let ((alist (bmkp-snippet-alist-only)))
+ (list (bmkp-read-bookmark-for-type "snippet" alist nil nil 'bmkp-snippet-history nil
+ "Copy snippet to kill ring"))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-snippet-alist-only))))
+ (bmkp-jump-1 bookmark 'ignore))
+
+;; Desktop bookmarks
+;;;###autoload (autoload 'bmkp-set-desktop-bookmark "bookmark+")
+(defun bmkp-set-desktop-bookmark (desktop-file &optional nosavep)
+ ; Bound globally to `C-x x K', `C-x r K', `C-x x c K'
+ "Save the desktop as a bookmark.
+You are prompted for the desktop-file location and the bookmark name.
+The default value for the desktop-file location is the current value
+of `desktop-base-file-name'. As always, you can use `M-n' to retrieve
+the default value.
+
+With a prefix arg, set a bookmark to an existing desktop file - do not
+save the current desktop. Do not overwrite the file whose name you
+enter, just use it to set the bookmark.
+
+If you also use library Icicles, then the desktop files of all
+existing desktop bookmarks are available during the desktop file-name
+completion as proxy candidates. To see them, use `C-M-_' to turn on
+the display of proxy candidates."
+ (interactive
+ (progn (unless (condition-case nil (require 'desktop nil t) (error nil))
+ (error "You must have library `desktop.el' to use this command"))
+ (let ((icicle-proxy-candidates (and (boundp 'icicle-mode) icicle-mode
+ (mapcar (lambda (bmk)
+ (bookmark-prop-get
+ bmk 'desktop-file))
+ (bmkp-desktop-alist-only))))
+ (icicle-unpropertize-completion-result-flag t))
+ (list (read-file-name
+ (if current-prefix-arg "Use existing desktop file: " "Save desktop in file: ")
+ bmkp-desktop-default-directory
+ (if (boundp 'desktop-base-file-name) desktop-base-file-name desktop-basefilename)
+ current-prefix-arg)
+ current-prefix-arg))))
+ (unless (or nosavep (condition-case nil (require 'desktop nil t) (error nil)))
+ (error "You must have library `desktop.el' to use this command"))
+ (unless (file-name-absolute-p desktop-file)
+ (setq desktop-file (expand-file-name desktop-file bmkp-desktop-default-directory)))
+ (set-text-properties 0 (length desktop-file) nil desktop-file)
+ (if nosavep
+ (unless (bmkp-desktop-file-p desktop-file) (error "Not a desktop file: `%s'" desktop-file))
+ (bmkp-desktop-save desktop-file))
+ (let ((bookmark-make-record-function (lexical-let ((df desktop-file))
+ (lambda () (bmkp-make-desktop-record df))))
+ (current-prefix-arg 99)) ; Use all bookmarks for completion, for `bookmark-set'.
+ (call-interactively #'bookmark-set)))
+
+(defun bmkp-desktop-save (desktop-file)
+ "Save current desktop in DESKTOP-FILE."
+ (let ((desktop-basefilename (file-name-nondirectory desktop-file)) ; Emacs < 22
+ (desktop-base-file-name (file-name-nondirectory desktop-file)) ; Emacs 23+
+ (desktop-dir (file-name-directory desktop-file))
+ (desktop-restore-eager t) ; Don't bother with lazy restore.
+ (desktop-globals-to-save (bmkp-remove-if (lambda (elt) (memq elt bmkp-desktop-no-save-vars))
+ desktop-globals-to-save)))
+ (cond ((< emacs-major-version 22) ; Emacs 22 introduced `RELEASE' (locking).
+ (desktop-save desktop-dir))
+ ((or (< emacs-major-version 24) (and (= emacs-major-version 24) (< emacs-minor-version 4)))
+ (desktop-save desktop-dir 'RELEASE))
+ (t ; Emacs 24.4 introduced `AUTOSAVE'.
+ (desktop-save desktop-dir 'RELEASE 'AUTOSAVE)))
+ (message "Desktop saved in `%s'" desktop-file)))
+
+(unless (fboundp 'desktop-full-file-name) ; Emacs < 22. (This is the vanilla definition.)
+ (defun desktop-full-file-name (&optional dirname)
+ "Return the full name of the desktop file in DIRNAME.
+DIRNAME omitted or nil means use `desktop-dirname'."
+ (expand-file-name desktop-basefilename (or dirname desktop-dirname))))
+
+(defun bmkp-desktop-save-as-last ()
+ "Save desktop to the file that is the value of `bmkp-desktop-current-file'.
+Do nothing if any of these are true:
+
+ * `desktop-save-mode' is non-nil
+ * `bmkp-desktop-current-file' is nil
+ * `bmkp-desktop-current-file' does not seem to be current (a non-bookmark
+ desktop was last made current)
+
+You might want to use this on `kill-emacs-hook'."
+ (when (and (not desktop-save-mode) bmkp-desktop-current-file
+ (bmkp-same-file-p (desktop-full-file-name) bmkp-desktop-current-file))
+ (bmkp-desktop-save bmkp-desktop-current-file)))
+
+;;; (defun bmkp-desktop-file-p (file)
+;;; "Return non-nil if FILE is readable and appears to be a desktop file.
+;;; FILE is a file-name string."
+;;; (and (stringp file)
+;;; (file-readable-p file)
+;;; (with-current-buffer (let ((enable-local-variables nil)) (find-file-noselect file))
+;;; (goto-char (point-min))
+;;; (and (zerop (forward-line 2))
+;;; (bmkp-looking-at-p "^;; Desktop File for Emacs$")))))
+
+;; Similar to `icicle-file-desktop-p' in `icicles-fn.el'.
+;; This is better than using `find-file-noselect', which visits the file and leaves its buffer.
+(defun bmkp-desktop-file-p (filename)
+ "Return non-nil if FILENAME names a desktop file."
+ (when (consp filename) (setq filename (car filename)))
+ (and (stringp filename)
+ (file-readable-p filename)
+ (not (file-directory-p filename))
+ (with-temp-buffer
+ (insert-file-contents-literally filename nil 0 1000)
+ (goto-char (point-min))
+ (and (zerop (forward-line 2))
+ (bmkp-looking-at-p "^;; Desktop File for Emacs"))))) ; No $, because maybe eol chars (e.g. ^M).
+
+(defun bmkp-make-desktop-record (desktop-file)
+ "Create and return a desktop bookmark record.
+DESKTOP-FILE is the absolute file name of the desktop file to use."
+ `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT nil nil 'NO-REGION)
+ (filename . ,bmkp-non-file-filename)
+ (desktop-file . ,desktop-file)
+ (handler . bmkp-jump-desktop)))
+
+(defun bmkp-jump-desktop (bookmark)
+ "Jump to desktop bookmark BOOKMARK.
+Handler function for record returned by `bmkp-make-desktop-record'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (let ((desktop-file (bookmark-prop-get bookmark 'desktop-file)))
+ (unless (condition-case nil (require 'desktop nil t) (error nil))
+ (error "You must have library `desktop.el' to use this command"))
+ ;; (unless desktop-file (error "Not a desktop-bookmark: %S" bookmark)) ; Shouldn't happen.
+ (bmkp-desktop-change-dir desktop-file)
+ (unless (bmkp-desktop-read desktop-file) (error "Could not load desktop file"))))
+
+;; Derived from code in `desktop-change-dir'.
+;;;###autoload (autoload 'bmkp-desktop-change-dir "bookmark+")
+(defun bmkp-desktop-change-dir (desktop-file)
+ "Change to desktop saved in DESKTOP-FILE.
+Kill the desktop as specified by variables `desktop-save-mode' and
+ `desktop-save' (starting with Emacs 22).
+Clear the desktop and load DESKTOP-FILE."
+ (interactive
+ (progn (unless (condition-case nil (require 'desktop nil t) (error nil))
+ (error "You must have library `desktop.el' to use this command"))
+ (list (let ((icicle-unpropertize-completion-result-flag t))
+ (read-file-name "Change to desktop file: " bmkp-desktop-default-directory)))))
+ (unless (condition-case nil (require 'desktop nil t) (error nil))
+ (error "You must have library `desktop.el' to use this command"))
+ (unless (file-name-absolute-p desktop-file)
+ (setq desktop-file (expand-file-name desktop-file bmkp-desktop-default-directory)))
+ (set-text-properties 0 (length desktop-file) nil desktop-file)
+ (let ((desktop-basefilename (file-name-nondirectory desktop-file)) ; Emacs < 22
+ (desktop-base-file-name (file-name-nondirectory desktop-file)) ; Emacs 23+
+ (desktop-dir (file-name-directory desktop-file))
+ (desktop-restore-eager t) ; Don't bother with lazy restore.
+ (desktop-globals-to-save (bmkp-remove-if (lambda (elt) (memq elt bmkp-desktop-no-save-vars))
+ desktop-globals-to-save)))
+ (bmkp-desktop-kill)
+ (desktop-clear)
+ (if (< emacs-major-version 22) (desktop-read) (desktop-read desktop-dir))))
+
+;; Derived from code in `desktop-kill'.
+(defun bmkp-desktop-kill ()
+ "If `desktop-save-mode' is non-nil, do what `desktop-save' says to do.
+In any case, release the lock on the desktop file.
+This function does nothing in Emacs versions prior to Emacs 22."
+ ;; We assume here: `desktop.el' has been loaded and `desktop-dirname' is defined.
+ (when (and (boundp 'desktop-save-mode) ; Not defined in Emacs 20-21.
+ desktop-save-mode
+ (let ((exists (file-exists-p (desktop-full-file-name))))
+ (or (eq desktop-save t)
+ (and exists (memq desktop-save '(ask-if-new if-exists)))
+ (and (or (memq desktop-save '(ask ask-if-new))
+ (and exists (eq desktop-save 'ask-if-exists)))
+ (y-or-n-p "Save current desktop first? ")))))
+ (condition-case err
+ (if (or (< emacs-major-version 24)
+ (and (= emacs-major-version 24) (< emacs-minor-version 4)))
+ (desktop-save desktop-dirname 'RELEASE)
+ (desktop-save desktop-dirname 'RELEASE 'AUTOSAVE)) ; Emacs 24.4 introduced `AUTOSAVE'.
+ (file-error (unless (yes-or-no-p "Error while saving the desktop. IGNORE? ")
+ (signal (car err) (cdr err))))))
+ ;; Just release lock, regardless of whether this Emacs process is the owner.
+ (when (fboundp 'desktop-release-lock) (desktop-release-lock))) ; Not defined for Emacs 20.
+
+;; Derived from code in `desktop-read'.
+;;;###autoload (autoload 'bmkp-desktop-read "bookmark+")
+(defun bmkp-desktop-read (file)
+ "Load desktop-file FILE, then run `desktop-after-read-hook'.
+Return t if FILE was loaded, nil otherwise."
+ (interactive)
+ (unless (file-name-absolute-p file) ; Should never happen.
+ (setq file (expand-file-name file bmkp-desktop-default-directory)))
+ (when (file-directory-p file) (error "`%s' is a directory, not a file" file))
+ (setq desktop-dirname (file-name-directory file))
+ (if (not (file-readable-p file))
+ nil ; Return nil, meaning not loaded.
+ (let ((desktop-restore-eager t) ; Don't bother with lazy restore.
+ (desktop-first-buffer nil)
+ (desktop-buffer-ok-count 0)
+ (desktop-buffer-fail-count 0)
+ (desktop-save nil)) ; Prevent desktop saving during eval of desktop buffer.
+ (when (fboundp 'desktop-lazy-abort) (desktop-lazy-abort)) ; Emacs 22+.
+ (load file t t t)
+ (when (boundp 'desktop-file-modtime) ; Emacs 22+
+ (setq desktop-file-modtime (nth 5 (file-attributes file))))
+ ;; `desktop-create-buffer' puts buffers at end of the buffer list.
+ ;; We want buffers existing prior to evaluating the desktop (and not reused) to be placed
+ ;; at the end of the buffer list, so we move them here.
+ (mapc 'bury-buffer (nreverse (cdr (memq desktop-first-buffer (nreverse (buffer-list))))))
+ (bmkp--pop-to-buffer-same-window (car (buffer-list)))
+ (run-hooks 'desktop-delay-hook)
+ (setq desktop-delay-hook ())
+ (run-hooks 'desktop-after-read-hook)
+ (when (boundp 'desktop-buffer-ok-count) ; Emacs 22+
+ (message "Desktop: %d buffer%s restored%s%s." desktop-buffer-ok-count
+ (if (= 1 desktop-buffer-ok-count) "" "s")
+ (if (< 0 desktop-buffer-fail-count)
+ (format ", %d failed to restore" desktop-buffer-fail-count)
+ "")
+ (if (and (boundp 'desktop-buffer-args-list) desktop-buffer-args-list)
+ (format ", %d to be restored lazily" (length desktop-buffer-args-list))
+ "")))
+ t))) ; Return t, meaning successfully loaded.
+
+;;;###autoload (autoload 'bmkp-desktop-delete "bookmark+")
+(defun bmkp-desktop-delete (bookmark)
+ "Delete desktop bookmark BOOKMARK, and delete its desktop file.
+Release the lock file in that desktop's directory.
+\(This means that if you currently have locked a different desktop
+in the same directory, then you will need to relock it.)
+BOOKMARK is a bookmark name or a bookmark record."
+ (interactive
+ (let ((alist (bmkp-desktop-alist-only)))
+ (list (bmkp-read-bookmark-for-type "desktop" alist nil nil 'bmkp-desktop-history "Delete "))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-desktop-alist-only))))
+ (let ((desktop-file (bookmark-prop-get bookmark 'desktop-file)))
+ (unless desktop-file (error "Not a desktop-bookmark: `%s'" bookmark))
+ ;; Release the desktop lock file in the same directory as DESKTOP-FILE.
+ ;; This will NOT be the right thing to do if a desktop file different from DESKTOP-FILE
+ ;; is currently locked in the same directory.
+ (let ((desktop-dir (file-name-directory desktop-file)))
+ (when (fboundp 'desktop-release-lock) (desktop-release-lock))) ; Not defined for Emacs 20.
+ (when (file-exists-p desktop-file) (delete-file desktop-file)))
+ (bookmark-delete bookmark))
+
+;; Icicle search-hits bookmarks
+(defun bmkp-jump-icicle-search-hits (bookmark)
+ "Handle an Icicles search-hits bookmark BOOKMARK."
+ (unless (and (boundp 'icicle-mode) icicle-mode (icicle-completing-p)
+ (condition-case nil (icicle-barf-if-outside-Completions-and-minibuffer) (error nil)))
+ (error "You can use this bookmark only in Icicle mode, and only during completion"))
+ (let ((raw-cands (bookmark-prop-get bookmark 'hits)))
+ (setq icicle-saved-completion-candidates
+ (if icicle-multi-completing-p
+ raw-cands ; But will not work if RAW-CANDS are not multi-completions.
+ (mapcar #'icicle-transform-multi-completion raw-cands)))
+ (if bmkp-icicles-search-hits-retrieve-more
+ (icicle-candidate-set-retrieve-more)
+ (icicle-candidate-set-retrieve))))
+
+;;;###autoload (autoload 'bmkp-retrieve-icicle-search-hits "bookmark+")
+(defun bmkp-retrieve-icicle-search-hits () ; Bound to `C-x C-M-<' during Icicles completion.
+ "Replace the current set of Icicles search hits by those from a bookmark.
+You are prompted for the bookmark name.
+This makes sense only if the buffer(s) or file(s) currently being
+searched correspond to the recorded search hits."
+ (interactive)
+ (when (interactive-p) (icicle-barf-if-outside-Completions-and-minibuffer))
+ (bmkp-retrieve-icicle-search-hits-1))
+
+;;;###autoload (autoload 'bmkp-retrieve-more-icicle-search-hits "bookmark+")
+(defun bmkp-retrieve-more-icicle-search-hits () ; Bound to `C-x C-<' during Icicles completion.
+ "Add the Icicles search hits from a bookmark to the current set of hits.
+You are prompted for the bookmark name.
+This makes sense only if the buffer(s) or file(s) currently being
+searched correspond to the recorded search hits."
+ (interactive)
+ (when (interactive-p) (icicle-barf-if-outside-Completions-and-minibuffer))
+ (bmkp-retrieve-icicle-search-hits-1 'MORE))
+
+(defun bmkp-retrieve-icicle-search-hits-1 (&optional morep)
+ "Helper for `bmkp-retrieve-(more-)icicle-search-hits'."
+ (unless (and (boundp 'icicle-searching-p) icicle-searching-p)
+ (error "This command can be used only during Icicles search"))
+ (let* ((hits-bmks (bmkp-icicles-search-hits-alist-only))
+ (bmk (let ((icicle-completion-candidates
+ icicle-completion-candidates)
+ (enable-recursive-minibuffers t))
+ (bookmark-completing-read "Bookmark name"
+ (mapcar #'bmkp-bookmark-name-from-record hits-bmks)
+ hits-bmks
+ nil
+ nil
+ 'USE-NIL-ALIST-P)))
+ (bmkp-icicles-search-hits-retrieve-more morep))
+ (bookmark-jump bmk)))
+
+;;;###autoload (autoload 'bmkp-set-icicle-search-hits-bookmark "bookmark+")
+(defun bmkp-set-icicle-search-hits-bookmark () ; Bound to `C-x C-M->' during Icicles completion.
+ "Record the current set of Icicles search-hit candidates as a bookmark."
+ (interactive)
+ (unless (and (boundp 'icicle-searching-p) icicle-searching-p)
+ (error "This command can be used only during Icicles search"))
+ (unless icicle-completion-candidates (error "No search hits to record"))
+ (when (interactive-p) (icicle-barf-if-outside-Completions-and-minibuffer))
+ (let ((bookmark-make-record-function 'bmkp-make-icicle-search-hits-record)
+ (enable-recursive-minibuffers t))
+ (call-interactively #'bookmark-set)))
+
+(defun bmkp-make-icicle-search-hits-record ()
+ "Create and return an Icicles search-hits bookmark record."
+ `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT nil nil 'NO-REGION)
+ (filename . ,bmkp-non-file-filename)
+ (hits . ,(mapcar #'bmkp-unpropertized-string icicle-completion-candidates))
+ (handler . bmkp-jump-icicle-search-hits)))
+
+;; Variable-list bookmarks
+(when (boundp 'zz-izones-var) ; In `zones.el'.
+ (defun bmkp-set-izones-bookmark (&optional variable msgp)
+ "Save a ring of buffer zones as a bookmark.
+The zones can use markers or readable-marker objects for any
+buffers. You need library `zones.el' to use the bookmark created.
+
+By default, the zones are those defined by the variable that is the
+current value of `zz-izones-var', which defaults to `zz-izones'. With
+a prefix arg you are prompted for a different variable to use.
+
+Non-interactively, VARIABLE is the restrictions variable to use."
+ (interactive (let ((var (or (and current-prefix-arg (zz-read-any-variable "Variable: " zz-izones-var))
+ zz-izones-var)))
+ (list var t)))
+ (unless variable (setq variable zz-izones-var))
+ (let ((bookmark-make-record-function
+ (lambda ()
+ (bmkp-make-variable-list-record
+ `((,variable ; Format: (NUM BEGM ENDM), BEGM and ENDM are readable-marker objects.
+ . ,(mapcar (lambda (xx)
+ (let ((id (nth 0 xx))
+ (beg (nth 1 xx))
+ (end (nth 2 xx))
+ (extra (nthcdr 3 xx)))
+ `(,id ,(zz-readable-marker beg) ,(zz-readable-marker end) ,@extra)))
+ (symbol-value variable))))))))
+ (call-interactively #'bookmark-set)
+ (when (and msgp (not (featurep 'zones))
+ (message "Bookmark created, but you need `zones.el' to use it")))))
+
+ )
+
+;;;###autoload (autoload 'bmkp-wrap-bookmark-with-last-kbd-macro "bookmark+")
+(defun bmkp-wrap-bookmark-with-last-kbd-macro (sequence bookmark &optional arg msgp)
+ ; Bound globally to `C-x x C-k'.
+ "Return a SEQUENCE bookmark that invokes BOOKMARK plus `last-kbd-macro'.
+If bookmark SEQUENCE does not yet exist, create it. Else, update it.
+You are prompted for the SEQUENCE and BOOKMARK names.
+
+BOOKMARK can be any kind of bookmark. A special case is when it is a
+sequence bookmark:
+
+ * If BOOKMARK is the same as SEQUENCE and is an existing sequence
+ bookmark then it is updated only by appending the keyboard macro to
+ the sequence.
+
+ * If BOOKMARK is a sequence bookmark different from SEQUENCE then
+ SEQUENCE is updated to invoke the sequence in BOOKMARK plus
+ `last-kbd-macro' either before or after the other bookmarks of
+ SEQUENCE, according to the prefix arg, which is passed to
+ `bmkp-set-sequence-bookmark'."
+ (interactive (list (bmkp-completing-read-lax "Sequence bookmark" (bmkp-new-bookmark-default-names))
+ (bmkp-completing-read-lax "Bookmark" (bmkp-new-bookmark-default-names))
+ current-prefix-arg
+ 'MSGP))
+ (unless last-kbd-macro (error "No keyboard macro defined"))
+ (let ((kbd-macro-vec (read-kbd-macro (format-kbd-macro last-kbd-macro) 'VECTOR)))
+ (bmkp-set-sequence-bookmark sequence (if (equal bookmark sequence)
+ (list kbd-macro-vec)
+ (list bookmark kbd-macro-vec))
+ arg msgp)))
+
+;; Not used yet.
+(defun bmkp-pop-to-readable-marker (readable-marker)
+ "Go to the marker recorded as persistent READABLE-MARKER.
+The form of the input is (marker MARKER-BUFFER MARKER-POSITION."
+ (pop-to-buffer (cadr readable-marker))
+ (goto-char (cadr (cdr readable-marker))))
+
+;;;###autoload (autoload 'bmkp-set-sequence-bookmark "bookmark+")
+(defun bmkp-set-sequence-bookmark (seqname bookmark-names &optional arg msgp)
+ ; Bound globally to `C-x x c s'.
+ "Create or update a sequence bookmark named SEQNAME from BOOKMARK-NAMES.
+If a sequence bookmark named SEQNAME does not exist then create one.
+Else act on the existing bookmarks in bookmark SEQNAME as follows:
+
+ * no prefix arg: Append BOOKMARK-NAMES to those present.
+ * prefix arg < 0: Replace those present with BOOKMARK-NAMES.
+ * other prefix arg: Prepend BOOKMARK-NAMES to those present.
+
+You are prompted for SEQNAME and each of the BOOKMARK-NAMES.
+
+When entering each item of BOOKMARK-NAMES you can enter an existing or
+future bookmark name, or you can enter the name of a function or a
+named keyboard macro (provided what you type does not match a bookmark
+name). If a function or keyboard macro, then a function bookmark is
+created for it and that bookmark is included in the sequence.
+
+When the sequence bookmark is invoked (\"jumped to\"), its bookmarks
+are invoked in order. In particular, any given bookmark is invoked
+once for each of its occurrences in the sequence.
+
+From Lisp code:
+
+BOOKMARK-NAMES is generally a list of bookmarks or bookmark names
+ \(strings).
+
+ Each item in BOOKMARK-NAMES can alternatively be one of the
+ following, in which case a function bookmark is created for it and is
+ used in the sequence.
+
+ * a keyboard macro as a vector
+ * a function, which includes a lambda form or a symbol whose
+ function value is a function or a keyboard macro.
+
+ If an item in BOOKMARK-NAMES is a sequence bookmark then its
+ bookmarks are used as if they were items of BOOKMARK-NAMES.
+
+MSGP non-nil means possibly interact with the user, showing messages."
+ (interactive (list
+ (if (< (prefix-numeric-value current-prefix-arg) 0)
+ (bookmark-completing-read "Replace existing sequence bookmark"
+ nil
+ (bmkp-sequence-alist-only)
+ nil
+ nil
+ 'USE-NIL-ALIST-P)
+ (bmkp-completing-read-lax "Create or update sequence bookmark"
+ (bmkp-new-bookmark-default-names)
+ (bmkp-sequence-alist-only)))
+ (bmkp-completing-read-bookmarks nil nil nil 'lax)
+ current-prefix-arg
+ 'MSGP))
+ (let* ((seq (bmkp-get-bookmark-in-alist seqname 'NOERROR))
+ (exists (and seq (bmkp-sequence-bookmark-p seq)))
+ (replacing t)
+ (bnames ())
+ fun)
+ (dolist (bname bookmark-names)
+ (cond ((or (functionp (setq fun bname)) ; Function from Lisp.
+ (vectorp fun) ; Keyboard macro.
+ (functionp (setq fun (condition-case nil ; Function name from user
+ (bmkp-read-from-whole-string bname)
+ (error nil)))))
+ (let ((fun-bmk-name
+ (cond ((symbolp fun) (symbol-name fun)) ; Named function. Use its name.
+ ((vectorp fun) (format-kbd-macro fun)) ; Keyboard macro. Use human-readable strg
+ ;; Lambda form. Use as much as possible, but uniquify (no such symbol name).
+ (t (let ((ii 1)
+ (len (length bname))
+ (trial (make-string (1+ bmkp-bookmark-name-length-max) 88)))
+ (while (and (< ii len) (> (length trial) bmkp-bookmark-name-length-max))
+ (setq trial (make-temp-name (substring bname 0 (- ii)))))
+ (while (intern-soft
+ (setq trial (make-temp-name (substring bname 0 (- ii))))))
+ trial)))))
+ (push (bmkp-bookmark-name-from-record (bmkp-make-function-bookmark fun-bmk-name fun))
+ bnames)))
+ ((bmkp-sequence-bookmark-p bname) ; Sequence bookmark.
+ (setq bnames (append (reverse (bookmark-prop-get bname 'sequence)) bnames)))
+ ((stringp bname) (push bname bnames)) ; Bookmark name.
+ ((bmkp-get-bookmark bname 'NOERROR) ; Full bookmark.
+ (push (bmkp-bookmark-name-from-record bname) bnames))
+ (t (error "Bad BOOKMARK-NAMES arg to `bmkp-set-sequence-bookmark': `%S'"
+ bookmark-names)))) ; Punt.
+ (setq bnames (nreverse bnames))
+ (if (not exists)
+ (when msgp (message "Creating sequence bookmark..."))
+ (if (< (prefix-numeric-value arg) 0)
+ (when msgp (message "REPLACING existing sequence bookmark...") (sit-for 0.5))
+ (when msgp (message "%sing to sequence bookmark..." (if arg "Prepend" "Append")) (sit-for 0.5))
+ (setq replacing nil
+ bnames (if arg
+ (nconc bnames (bookmark-prop-get seq 'sequence))
+ (nconc (bookmark-prop-get seq 'sequence) bnames)))))
+ (let ((bookmark-make-record-function `(lambda () (bmkp-make-sequence-record ',bnames))))
+ (bookmark-set seqname))
+ (when msgp (message "Sequence `%s' %s" seqname (if exists
+ (if replacing "replaced" "updated")
+ "created")))))
+
+(defun bmkp-make-sequence-record (bookmark-names)
+ "Create and return a sequence bookmark record.
+BOOKMARK-NAMES is a list of names of the bookmarks to be invoked in
+sequence."
+ (let ((record `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT 0 nil 'NO-REGION)
+ (sequence . ,bookmark-names)
+ (handler . bmkp-jump-sequence))))
+ record))
+
+(when (require 'kmacro nil t) ; Emacs 22+
+
+ (defun bmkp-set-kmacro-bookmark (bookmark-name keyboard-macro &optional msg-p)
+ "Create a function bookmark named BOOKMARK-NAME from KEYBOARD-MACRO.
+Prompt for BOOKMARK-NAME and the name of the keyboard macro to use.
+With a prefix arg, use `last-kbd-macro' as the keyboard macro."
+ (interactive
+ (let ((bname (bmkp-completing-read-lax "Bookmark"))
+ (kmac (if current-prefix-arg
+ last-kbd-macro
+ (symbol-function (intern (completing-read "Keyboard macro name: "
+ obarray
+ (lambda (elt)
+ (and (fboundp elt)
+ (or (stringp (symbol-function elt))
+ (vectorp (symbol-function elt))
+ (get elt 'kmacro))))
+ t))))))
+ (list bname kmac 'MSG)))
+ (let* ((bmk (bmkp-get-bookmark-in-alist bookmark-name 'NOERROR))
+ (exists (and bmk (bmkp-function-bookmark-p bmk))))
+ (bmkp-make-function-bookmark bookmark-name keyboard-macro msg-p)
+ (when msg-p
+ (message "Function bookmark `%s' %s" bookmark-name (if exists "replaced" "created")))))
+
+ (defun bmkp-set-kmacro-list-bookmark (bookmark-name)
+ "Save all current keyboard macros as a kmacro-list bookmark."
+ (interactive (list (bmkp-completing-read-lax "Bookmark")))
+ (let ((bookmark-make-record-function (lambda ()
+ (bmkp-make-kmacro-list-record
+ (cons (kmacro-ring-head) kmacro-ring)))))
+ (bookmark-set bookmark-name)))
+
+ (defun bmkp-make-kmacro-list-record (kmacros)
+ "Create and return a kmacro-list bookmark record.
+KMACROS is the list of kmacros to save. It has the same form as
+`kmacro-ring'.
+
+Each entry in KMACROS thus has the form (MACRO COUNTER FORMAT)."
+ (let ((record `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT nil nil 'NO-REGION)
+ (kmacros . ,kmacros)
+ (handler . bmkp-jump-kmacro-list))))
+ record))
+
+ )
+
+;;;###autoload (autoload 'bmkp-set-variable-list-bookmark "bookmark+")
+(defun bmkp-set-variable-list-bookmark (variables)
+ "Save a list of variables as a bookmark.
+Interactively, read the variables to save, using
+`bmkp-read-variables-completing'."
+ (interactive (list (bmkp-read-variables-completing)))
+ (let ((bookmark-make-record-function (lexical-let ((vars variables))
+ (lambda () (bmkp-make-variable-list-record vars)))))
+ (call-interactively #'bookmark-set)))
+
+;; Not used in the Bookmark+ code. Available for users to create varlist bookmark non-interactively.
+(defun bmkp-create-variable-list-bookmark (bookmark-name vars vals &optional buffer-name)
+ "Create a variable-list bookmark named BOOKMARK-NAME from VARS and VALS.
+VARS and VALS are corresponding lists of variables and their values.
+
+Optional arg BUFFER-NAME is the buffer name to use for the bookmark (a
+string). This is useful if some of the variables are buffer-local.
+If BUFFER-NAME is nil, the current buffer name is recorded."
+ (eval `(multiple-value-bind ,vars ',vals
+ (let ((bookmark-make-record-function (lexical-let ((vs vars)
+ (buf buffer-name))
+ (lambda () (bmkp-make-variable-list-record vs buf)))))
+ (bookmark-set ,bookmark-name)))))
+
+(defun bmkp-read-variables-completing (&optional option)
+ "Read variable names with completion, and return them as a list of symbols.
+Reads names one by one, until you hit `RET' twice consecutively.
+Non-nil argument OPTION means read only user option names."
+ (bookmark-maybe-load-default-file)
+ (let ((var (bmkp-read-variable "Variable (RET for each, empty input to finish): " option))
+ (vars ())
+ old-var)
+ (while (not (string= "" var))
+ (add-to-list 'vars var)
+ (setq var (bmkp-read-variable "Variable: " option)))
+ (nreverse vars)))
+
+(defun bmkp-read-variable (prompt &optional option default-value)
+ "Read name of a variable and return it as a symbol.
+Prompt with string PROMPT.
+With non-nil OPTION, read the name of a user option.
+The default value is DEFAULT-VALUE if non-nil, or the nearest symbol
+to the cursor if it is a variable."
+ (setq option (if option 'user-variable-p 'boundp))
+ (let ((symb (cond ((fboundp 'symbol-nearest-point)
+ (symbol-nearest-point)) ; In `thingatpt+.el'.
+ ((fboundp 'symbol-at-point) (symbol-at-point))
+ (t nil)))
+ (enable-recursive-minibuffers t)
+ (icicle-unpropertize-completion-result-flag t))
+ (when (and default-value (symbolp default-value))
+ (setq default-value (symbol-name default-value)))
+ (intern (completing-read prompt obarray option t nil 'minibuffer-history
+ (or default-value (and (funcall option symb) (symbol-name symb)))
+ t))))
+
+(defun bmkp-make-variable-list-record (variables &optional buffer-name)
+ "Create and return a variable-list bookmark record.
+VARIABLES is the list of variables to save.
+Each entry in VARIABLES is either a variable (a symbol) or a cons
+ whose car is a variable and whose cdr is the variable's value.
+
+Optional arg BUFFER-NAME is the buffer to use for the bookmark. This
+is useful if some of the variables are buffer-local. If BUFFER-NAME
+is nil, the current buffer is used."
+ (let ((record `(,@(bookmark-make-record-default 'NO-FILE 'NO-CONTEXT nil nil 'NO-REGION)
+ (filename . ,bmkp-non-file-filename)
+ (variables . ,(or (bmkp-printable-vars+vals variables)
+ (error "No variables to bookmark")))
+ (handler . bmkp-jump-variable-list))))
+ (when buffer-name (let ((bname (assq 'buffer-name record))) (setcdr bname buffer-name)))
+ record))
+
+(defun bmkp-printable-vars+vals (variables)
+ "Return an alist of printable VARIABLES paired with their values.
+Display a message for any variables that are not printable.
+VARIABLES is the list of variables. Each entry in VARIABLES is either
+ a variable (a symbol) or a cons whose car is a variable and whose cdr
+ is the variable's value."
+ (let ((vars+vals ())
+ (unprintables ()))
+ (dolist (var variables)
+ (let ((val (if (consp var) (cdr var) (symbol-value var))))
+ (if (bmkp-readable-p val)
+ (add-to-list 'vars+vals (if (consp var) var (cons var val)))
+ (add-to-list 'unprintables var))))
+ (when unprintables (message "Unsavable (unreadable) vars: %S" unprintables) (sit-for 3))
+ vars+vals))
+
+;; Same as `savehist-printable' in `savehist-20+.el', except added `print-circle' and `print-gensym' bindings.
+(defun bmkp-readable-p (value)
+ "Return non-nil if VALUE is Lisp-readable if printed using `prin1'."
+ (cond ((numberp value))
+ ((symbolp value))
+ ((and (stringp value) ; String with no text properties.
+ (if (fboundp 'equal-including-properties) ; Emacs 22+.
+ (equal-including-properties value (substring-no-properties value))
+ (and (null (text-properties-at 0 value))
+ (= 0 (next-property-change 0 value))))))
+ (t (with-temp-buffer
+ (condition-case nil
+ (let ((print-readably t)
+ (print-level nil)
+ (print-circle bmkp-propertize-bookmark-names-flag)
+ (print-gensym bmkp-propertize-bookmark-names-flag))
+ (prin1 value (current-buffer)) ; Print value into a buffer and try to read back.
+ (read (point-min-marker))
+ t)
+ (error nil)))))) ; Could not print and read back.
+
+(when (require 'kmacro nil t) ; Emacs 22
+
+ (defun bmkp-jump-kmacro-list (bookmark)
+ "Jump to kmacro-list bookmark BOOKMARK, restoring the keyboard macros.
+Handler function for record returned by
+`bmkp-make-kmacro-list-record'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (let ((buf (bmkp-get-buffer-name bookmark))
+ (kbd-macs (bookmark-prop-get bookmark 'kmacros)))
+ (unless (and buf (get-buffer buf))
+ (message "Bookmarked for non-existent buffer `%s', so using current buffer" buf) (sit-for 3)
+ (setq buf (current-buffer)))
+ (with-current-buffer buf
+ (let ((kmacs kbd-macs))
+ (when last-kbd-macro
+ (kmacro-push-ring (list last-kbd-macro kmacro-counter kmacro-counter-format-start)))
+ (kmacro-split-ring-element (pop kmacs))
+ (dolist (kmac kmacs) (kmacro-push-ring kmac))))
+ (message "Keyboard macros restored in buffer `%s': %S" buf (mapcar #'car kbd-macs))
+ (sit-for 3)))
+
+ )
+
+
+;; REPLACES ORIGINAL in `info.el':
+;;
+;; Respect `Info-bookmark-use-only-node-not-file-flag'.
+;;
+;; This code and the definition of `Info-bookmark-use-only-node-not-file-flag' are also in `info+.el',
+;; so that their feature is available if you use either `Info+' or `Bookmark+'.
+;;
+;; Note: This function name doesn't respect the naming convention for bookmark handler functions.
+;; This name gives the impression that this is a jump command.
+;;
+;;;###autoload (autoload 'Info-bookmark-jump "bookmark+")
+(defun Info-bookmark-jump (bookmark)
+ "Handler function for record returned by `Info-bookmark-make-record'.
+BOOKMARK is a bookmark name or a bookmark record.
+
+If `Info-bookmark-use-only-node-not-file-flag' is nil, and the
+recorded Info file is readable, then use it. If not, then go to the
+recorded Info node in the manual for the current Emacs version."
+ (require 'info) ; Needed only for Emacs 20-22: not autoloaded for `Info-find-node'.
+ (let* ((absfile (bookmark-prop-get bookmark 'filename))
+ (file (if (or Info-bookmark-use-only-node-not-file-flag (not (file-readable-p absfile)))
+ (file-name-nondirectory absfile)
+ absfile))
+ (info-node (bookmark-prop-get bookmark 'info-node))
+ (buf (save-window-excursion ; Vanilla FIXME: doesn't work with frames!
+ (Info-find-node file info-node) (current-buffer))))
+ (bookmark-default-handler `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark)))))
+
+(defun bmkp-jump-variable-list (bookmark)
+ "Jump to variable-list bookmark BOOKMARK, restoring the recorded values.
+Handler function for record returned by
+`bmkp-make-variable-list-record'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (let ((buf (bmkp-get-buffer-name bookmark))
+ (vars+vals (bookmark-prop-get bookmark 'variables)))
+ (unless (get-buffer buf)
+ (message "Bookmarked for non-existent buffer `%s', so using current buffer" buf) (sit-for 3)
+ (setq buf (current-buffer)))
+ (with-current-buffer buf
+ (dolist (var+val vars+vals)
+ (set (car var+val) (cdr var+val))))
+ (message "Variables restored in buffer `%s': %S" buf (mapcar #'car vars+vals))
+ (sit-for 3)))
+
+;; URL browse support
+(defun bmkp-make-url-browse-record (url)
+ "Create and return a url bookmark for `browse-url' to visit URL.
+The handler is `bmkp-jump-url-browse'."
+ (require 'browse-url)
+ (let ((url-0 (copy-sequence url)))
+ (set-text-properties 0 (length url) () url-0)
+ `((filename . ,bmkp-non-file-filename)
+ (location . ,url-0)
+ (handler . bmkp-jump-url-browse))))
+
+(defun bmkp-jump-url-browse (bookmark)
+ "Handler function for record returned by `bmkp-make-url-browse-record'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (require 'browse-url)
+ (let ((url (bookmark-prop-get bookmark 'location)))
+ (browse-url url)))
+
+
+;; EWW support
+(when (> emacs-major-version 24) ; Emacs 25+
+
+ ;; This is set by `bmkp-eww-rename-buffer' and used in `bmkp-jump-eww' for local var `after-render-function'.
+ (defvar bmkp-eww-new-buf-name nil
+ "If non-nil, the name of the EWW buffer to jump to.")
+ (make-variable-buffer-local 'bmkp-eww-new-buf-name)
+
+ ;; This is set by `bmkp-jump-eww' and used in `bmkp-eww-rename-buffer'.
+ (defvar bmkp-eww-jumping-p nil
+ "Non-nil only if we are currently jumping to an EWW bookmark.")
+ (make-variable-buffer-local 'bmkp-eww-jumping-p)
+
+ (defun bmkp-eww-title ()
+ "Return the web-page title of the current `eww-mode' buffer."
+ (plist-get eww-data :title))
+
+ (defun bmkp-eww-url ()
+ "Return the URL of the current `eww-mode' buffer."
+ (eww-current-url))
+
+ (defun bmkp-make-eww-record ()
+ "Make a record for an EWW buffer."
+ `(,(bmkp-eww-title)
+ (buffer-name . ,(bmkp-eww-new-buffer-name))
+ ,@(bookmark-make-record-default 'NO-FILE)
+ (location . ,(bmkp-eww-url))
+ (handler . bmkp-jump-eww)))
+
+ (add-hook 'eww-mode-hook (lambda () (set (make-local-variable 'bookmark-make-record-function)
+ 'bmkp-make-eww-record)))
+
+ (defun bmkp-eww-new-buffer-name ()
+ "Return a new buffer name for the current `eww-mode' buffer.
+The name format is determined by option `bmkp-eww-buffer-renaming'."
+ (concat "*eww*" (and bmkp-eww-buffer-renaming
+ (concat "-"
+ (bmkp-eww-title)
+ (let ((url (bmkp-eww-url)))
+ (and (eq 'url bmkp-eww-buffer-renaming)
+ (concat " " (if (>= (length url) 20) (substring url -20) url))))))))
+
+ (defun bmkp-jump-eww (bookmark)
+ "Handler function for record returned by `bmkp-make-eww-record'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (require 'eww)
+ (let ((buffer (or (and (not bmkp-eww-generate-buffer-flag)
+ (get-buffer (bmkp-get-buffer-name bookmark)))
+ (generate-new-buffer "*eww*"))) ; Might get renamed later.
+ ;; VAR `bmkp-eww-new-buf-name' is free here. It is bound in `bmkp-eww-rename-buffer'.
+ (after-render-function `(lambda ()
+ (when (and bmkp-eww-buffer-renaming bmkp-eww-new-buf-name)
+ (kill-buffer)
+ (set-buffer bmkp-eww-new-buf-name))
+ (bookmark-default-handler
+ `("" (buffer . ,(current-buffer))
+ . ,(bmkp-bookmark-data-from-record ,(car bookmark))))
+ (dolist (var '(bmkp-eww-jumping-p eww-after-render-hook))
+ (kill-local-variable var)))))
+ (setq bmkp-eww-jumping-p t)
+ (with-current-buffer buffer
+ (eww-mode)
+ (save-window-excursion ; Save window because it calls `pop-to-buffer-same-window'.
+ (eww (bookmark-location bookmark)))
+ (add-hook 'eww-after-render-hook after-render-function 'APPEND 'LOCAL))))
+
+ (defun bmkp-eww-rename-buffer (&rest _ignored)
+ "Rename current buffer according to option `bmkp-eww-buffer-renaming'.
+When jumping to EWW bookmark with nil `bmkp-eww-generate-buffer-flag',
+if the buffer has already been visited, set `bmkp-eww-new-buf-name' so
+that `bmkp-jump-eww' will use the already visited buffer."
+ (when bmkp-eww-buffer-renaming
+ (let ((new-bname (bmkp-eww-new-buffer-name)))
+ (condition-case nil
+ (rename-buffer new-bname)
+ ;; VAR `bmkp-eww-jumping-p' is free here. It is set in `bmkp-jump-eww'.
+ (error (if (and bmkp-eww-jumping-p (not bmkp-eww-generate-buffer-flag))
+ (setq bmkp-eww-new-buf-name new-bname) ; For `after-render-function' in `bmkp-jump-eww'.
+ (rename-buffer (generate-new-buffer-name new-bname))))))))
+
+ ;; The EWW buffer is renamed on each visit, if `bmkp-eww-buffer-renaming' is non-nil.
+ (eval-after-load "eww"
+ '(when (> emacs-major-version 24) ; Emacs 25+
+ (add-hook 'eww-after-render-hook 'bmkp-eww-rename-buffer)
+ (advice-add 'eww-restore-history :after 'bmkp-eww-rename-buffer)))
+
+
+ ;; Eval this so that even if the library is byte-compiled with Emacs 20,
+ ;; loading it into Emacs 22+ will define variable `bmkp-eww-auto-bookmark-mode'.
+ (eval '(define-minor-mode bmkp-eww-auto-bookmark-mode
+ "Toggle automatically setting a bookmark when you visit a URL with EWW.
+The bookmark name is the title of the web page.
+
+If option `bmkp-eww-auto-type' is `create-or-update' then such a
+bookmark is created for the URL if none exists. If the option value
+is `update-only' then no new bookmark is created automatically, but an
+existing bookmark is updated. (Updating a bookmark increments the
+recorded number of visits.) You can toggle the option using
+`\\[bmkp-toggle-eww-auto-type]'."
+ :init-value nil :global t :group 'bookmark-plus :require 'bookmark+
+ :lighter bmkp-automatic-bookmark-mode-lighter
+ :link `(url-link :tag "Send Bug Report"
+ ,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
+Bookmark bug: \
+&body=Describe bug here, starting with `emacs -Q'. \
+Don't forget to mention your Emacs and library versions."))
+ :link '(url-link :tag "Download" "https://www.emacswiki.org/emacs/download/bookmark%2b.el")
+ :link '(url-link :tag "Description" "https://www.emacswiki.org/emacs/BookmarkPlus")
+ :link '(emacs-commentary-link :tag "Commentary" "bookmark+")
+ (cond (bmkp-eww-auto-bookmark-mode
+ (add-hook 'eww-after-render-hook 'bmkp-set-eww-bookmark-here)
+ (advice-add 'eww-restore-history :after 'bmkp-set-eww-bookmark-here))
+ (t
+ (remove-hook 'eww-after-render-hook 'bmkp-set-eww-bookmark-here)
+ (advice-remove 'eww-restore-history 'bmkp-set-eww-bookmark-here)))
+ (when (interactive-p)
+ (message "Automatic EWW bookmarking is now %s"
+ (if bmkp-eww-auto-bookmark-mode
+ (if (eq bmkp-eww-auto-type 'update-only)
+ "ON, updating only"
+ "ON, creating or UPDATING")
+ "OFF")))))
+
+ (defun bmkp-set-eww-bookmark-here (&optional nomsg)
+ "Set an EWW bookmark for the URL of the current EWW buffer.
+The current buffer is assumed to be in `eww-mode' and visiting a URL."
+ (interactive)
+ (let* ((bname (bmkp-eww-title))
+ (url (bmkp-eww-url))
+ (bmk (bmkp-get-bookmark bname 'NO-ERROR))
+ (visits (and bmk (bookmark-prop-get bmk 'visits))))
+ (when bname
+ (cond ((and (not visits) (eq bmkp-eww-auto-type 'create-or-update))
+ (bookmark-set bname)
+ (unless nomsg (message "Created EWW bookmark `%s'" bname)))
+ (visits
+ (bmkp-record-visit bname 'BATCHP)
+ (bmkp-refresh/rebuild-menu-list bname nil)
+ (bmkp-maybe-save-bookmarks)
+ (unless nomsg (message "Updated EWW bookmark `%s'" bname)))))))
+
+ (defun bmkp-toggle-eww-auto-type (&optional msgp)
+ "Toggle the value of option `bmkp-eww-auto-type'."
+ (interactive "p")
+ (setq bmkp-eww-auto-type (if (eq bmkp-eww-auto-type 'create-or-update) 'update-only 'create-or-update))
+ (when msgp (message "`bmkp-eww-auto-bookmark-mode' now %s"
+ (if (eq bmkp-eww-auto-type 'create-or-update)
+ "CREATES, as well as updates, EWW bookmarks"
+ "only UPDATES EXISTING EWW bookmarks"))))
+
+
+ ;; You can use this to convert existing EWW bookmarks to Bookmark+ bookmarks.
+ ;;
+ (defun bmkp-convert-eww-bookmarks (eww-file bmk-file &optional msgp)
+ "Add bookmarks from EWW-FILE to BMK-FILE.
+EWW-FILE is a file of \"bookmarks\" created by EWW, which are not
+compatible with Emacs bookmarks. EWW-FILE is not modified.
+
+BMK-FILE is a Bookmark+ bookmarks file, which is an ordinary Emacs
+bookmarks file (possibly with Bookmark+-specific bookmarks).
+
+If BMK-FILE exists then it is updated to include the converted
+bookmarks. If it does not exist then it is created."
+ (interactive
+ (let* ((std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ bookmark-default-file
+ std-default)
+ bmkp-last-bookmark-file)))
+ (list (bmkp-read-bookmark-file-name "EWW bookmark file: "
+ nil
+ (expand-file-name "eww-bookmarks" user-emacs-directory)
+ t)
+ (bmkp-read-bookmark-file-name "Emacs bookmark file to update: "
+ (or (file-name-directory default) "~/")
+ (if (bmkp-same-file-p bmkp-current-bookmark-file
+ bmkp-last-bookmark-file)
+ (bmkp-default-bookmark-file)
+ bmkp-last-bookmark-file))
+ t)))
+ (when (file-directory-p eww-file) (error "`%s' is a directory, not a file" eww-file))
+ (unless (file-readable-p eww-file) (error "Cannot read bookmark file `%s'" eww-file))
+ (when (file-directory-p bmk-file) (error "`%s' is a directory, not a file" bmk-file))
+ (unless (file-readable-p bmk-file) (bmkp-empty-file bmk-file)) ; Create empty bookmark file.
+ (with-temp-buffer
+ (insert-file-contents eww-file)
+ (let ((bookmark-alist ())
+ url title created bmk)
+ (dolist (ebmk (read (current-buffer)))
+ (setq url (plist-get ebmk :url)
+ title (plist-get ebmk :title)
+ created (date-to-time (plist-get ebmk :time))
+ bmk `(,title
+ ,@(bookmark-make-record-default 'NO-FILE)
+ (location . ,url)
+ (handler . bmkp-jump-eww)))
+ (let ((buf-cell (assq 'buffer-name bmk))) (setcdr buf-cell "*eww*"))
+ (let ((created-cell (assq 'created bmk))) (setcdr created-cell created))
+ (push bmk bookmark-alist))
+ (bookmark-write-file bmk-file 'ADD)))
+ (when msgp (message "Wrote Bookmark file `%s'" bmk-file)))
+
+ )
+
+;; W3M support
+(defun bmkp-make-w3m-record ()
+ "Make a special entry for w3m buffers."
+ (require 'w3m) ; For `w3m-current-url'.
+ `(,w3m-current-title
+ ,@(bookmark-make-record-default 'NO-FILE)
+ (location . ,w3m-current-url)
+ (handler . bmkp-jump-w3m)))
+
+(add-hook 'w3m-mode-hook (lambda () (set (make-local-variable 'bookmark-make-record-function)
+ 'bmkp-make-w3m-record)))
+
+(defun bmkp-w3m-set-new-buffer-name ()
+ "Set the w3m buffer name according to the number of W3M buffers already open."
+ (require 'w3m) ; For `w3m-list-buffers'.
+ (let ((len (length (w3m-list-buffers 'nosort))))
+ (if (= len 0) "*w3m*" (format "*w3m*<%d>" (1+ len)))))
+
+(defalias 'bmkp-jump-w3m-new-session 'bmkp-jump-w3m-new-buffer)
+(defun bmkp-jump-w3m-new-buffer (bookmark)
+ "Jump to W3M bookmark BOOKMARK in a new buffer (in a new W3M tab)."
+ (require 'w3m)
+ (let ((buf (bmkp-w3m-set-new-buffer-name)))
+ (w3m-browse-url (bookmark-location bookmark) 'newsession)
+ (while (not (get-buffer buf)) (sit-for 1)) ; Be sure we have the W3M buffer.
+ (with-current-buffer (get-buffer-create buf)
+ (goto-char (point-min))
+ ;; Wait until data arrives in buffer, before setting region.
+ (while (eq (line-beginning-position) (line-end-position)) (sit-for 1)))
+ (bookmark-default-handler `("" (buffer . ,buf) . ,(bmkp-bookmark-data-from-record bookmark)))))
+
+(defalias 'bmkp-jump-w3m-only-one-tab 'bmkp-jump-w3m-only-one-buffer)
+(defun bmkp-jump-w3m-only-one-buffer (bookmark)
+ "Close all W3M sessions and jump to BOOKMARK in a new W3M buffer."
+ (require 'w3m)
+ (w3m-quit 'force) ; Be sure we start with an empty W3M buffer.
+ (w3m-browse-url (bookmark-location bookmark))
+ (with-current-buffer (get-buffer-create "*w3m*") (while (eq (point-min) (point-max)) (sit-for 1)))
+ (bookmark-default-handler `("" (buffer . "*w3m*") . ,(bmkp-bookmark-data-from-record bookmark))))
+
+(defalias 'bmkext-jump-w3m 'bmkp-jump-w3m)
+(defun bmkp-jump-w3m (bookmark)
+ "Handler function for record returned by `bmkp-make-w3m-record'.
+BOOKMARK is a bookmark name or a bookmark record.
+Use a new buffer (tab) if `bmkp-w3m-allow-multiple-buffers-flag' is
+non-nil."
+ (require 'w3m)
+ (if bmkp-w3m-allow-multiple-buffers-flag
+ (bmkp-jump-w3m-new-buffer bookmark)
+ (bmkp-jump-w3m-only-one-buffer bookmark)))
+
+
+;; GNUS support for Emacs < 24. More or less the same as `gnus-summary-bookmark-make-record' in Emacs 24+.
+;; But this:
+;;
+;; * Works for other Emacs versions as well.
+;; * Requires `gnus.el'.
+;; * Adds a `bmkp-non-file-filename' `filename' entry.
+;; * Uses `bmkp-jump-gnus', not `gnus-summary-bookmark-jump' as the handler.
+;;
+(defun bmkp-make-gnus-record ()
+ "Make a bookmark entry for a Gnus summary buffer.
+Current buffer can be the article buffer or the summary buffer."
+ (require 'gnus)
+ (let ((pos nil)
+ buf)
+ ;; If in article buffer, record point and buffer, then go to summary buffer
+ ;; and record bookmark there.
+ (unless (and (if (fboundp 'derived-mode-p)
+ (derived-mode-p 'gnus-summary-mode)
+ (eq major-mode 'gnus-summary-mode))
+ gnus-article-current)
+ (setq buf "art"
+ bookmark-yank-point (point)
+ bookmark-current-buffer (current-buffer))
+ (save-restriction (widen) (setq pos (point))) ; Position in article buffer.
+ (gnus-article-show-summary))
+ (let* ((grp (car gnus-article-current))
+ (art (cdr gnus-article-current))
+ (head (gnus-summary-article-header art))
+ (id (mail-header-id head)))
+ (unless buf (setq buf "sum"))
+ `((elt (gnus-summary-article-header) 1) ; Subject.
+ ,@(condition-case
+ nil
+ (bookmark-make-record-default ; POS = nil if started in summary buffer.
+ 'NO-FILE 'NO-CONTEXT pos nil 'NO-REGION)
+ (wrong-number-of-arguments (bookmark-make-record-default 'POINT-ONLY)))
+ (location . ,(format "Gnus-%s %s:%d:%s" buf grp art id))
+ (filename . ,bmkp-non-file-filename) (group . ,grp) (article . ,art) (message-id . ,id)
+ (handler . bmkp-jump-gnus))))) ; Vanilla Emacs 24+ uses `gnus-summary-bookmark-jump'.
+
+
+;; Vanilla Emacs 24+ uses `gnus-summary-bookmark-make-record' for these hooks.
+;; Better to use `bmkp-make-gnus-record' even for Emacs 24+, because `bmkp-jump-gnus' is better than
+;; `gnus-summary-bookmark-jump' (no `sit-for' if article buffer not needed).
+
+;; $$$$$$ (unless (> emacs-major-version 23) ; Emacs 24 has `gnus-summary-bookmark-make-record'.
+(add-hook 'gnus-summary-mode-hook (lambda ()
+ (set (make-local-variable 'bookmark-make-record-function)
+ 'bmkp-make-gnus-record)))
+
+;; $$$$$$ (unless (> emacs-major-version 23) ; Emacs 24 has `gnus-summary-bookmark-make-record'.
+(add-hook 'gnus-article-mode-hook (lambda ()
+ (set (make-local-variable 'bookmark-make-record-function)
+ 'bmkp-make-gnus-record)))
+
+;; More or less the same as `gnus-summary-bookmark-jump' in Emacs 24+.
+;; But this does not `sit-for' unless BUF is "Gnus-art".
+;;
+(defun bmkp-jump-gnus (bookmark)
+ "Handler function for record returned by `bmkp-make-gnus-record'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (let* ((group (bookmark-prop-get bookmark 'group))
+ (article (bookmark-prop-get bookmark 'article))
+ (id (bookmark-prop-get bookmark 'message-id))
+ (loc (bookmark-prop-get bookmark 'location))
+ (buf (if loc (car (split-string loc)) (bookmark-prop-get bookmark 'buffer))))
+ (if (< emacs-major-version 22) (gnus-fetch-group group) (gnus-fetch-group group (list article)))
+ (gnus-summary-insert-cached-articles)
+ (gnus-summary-goto-article id nil 'force)
+ ;; Go to article buffer if appropriate. Wait for it to be ready, so `bookmark-default-handler' has time
+ ;; to set the right position.
+ (when (equal buf "Gnus-art") (sit-for 1) (other-window 1))
+ (bookmark-default-handler `("" (buffer . ,buf) . ,(bmkp-bookmark-data-from-record bookmark)))))
+
+(defun bmkext-jump-gnus (bookmark) ; Compatibility code.
+ "`gnus-summary-bookmark-jump' if defined, else `bmkp-jump-gnus'."
+ (if (fboundp 'gnus-summary-bookmark-jump)
+ (gnus-summary-bookmark-jump bookmark) ; Emacs 24
+ (bmkp-jump-gnus bookmark)))
+
+
+;; `man' and `woman' support for Emacs < 24.
+
+(when (> emacs-major-version 20)
+ (defun bmkp-make-woman-record ()
+ "Create bookmark record for `man' page bookmark created by `woman'."
+ `(,@(bookmark-make-record-default 'NO-FILE)
+ (filename . ,woman-last-file-name) (handler . bmkp-jump-woman)))
+
+ (unless (> emacs-major-version 23)
+ (add-hook 'woman-mode-hook (lambda ()
+ (set (make-local-variable 'bookmark-make-record-function)
+ 'bmkp-make-woman-record)))))
+
+(defun bmkp-make-man-record ()
+ "Create bookmark record for `man' page bookmark created by `man'."
+ `(,@(bookmark-make-record-default 'NO-FILE)
+ (filename . ,bmkp-non-file-filename)
+ (man-args . ,Man-arguments) (handler . bmkp-jump-man)))
+
+(unless (> emacs-major-version 23)
+ (add-hook 'Man-mode-hook (lambda () (set (make-local-variable 'bookmark-make-record-function)
+ 'bmkp-make-man-record))))
+
+(defun bmkext-jump-woman (bookmark) ; Compatibility code.
+ "`woman-bookmark-jump' if defined, else `bmkp-jump-woman'."
+ (if (fboundp 'woman-bookmark-jump)
+ (woman-bookmark-jump bookmark) ; Emacs 24
+ (bmkp-jump-woman bookmark)))
+
+(defun bmkp-jump-woman (bookmark)
+ "Handler function for `man' page bookmark created by `woman'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (unless (> emacs-major-version 20)
+ (error "`woman' bookmarks are not supported in Emacs prior to Emacs 21"))
+ (bookmark-default-handler
+ `("" (buffer . ,(save-window-excursion (woman-find-file (bookmark-get-filename bookmark))
+ (current-buffer)))
+ . ,(bmkp-bookmark-data-from-record bookmark))))
+
+(defun bmkext-jump-man (bookmark) ; Compatibility code.
+ "`Man-bookmark-jump' if defined, else `bmkp-jump-man'."
+ (if (fboundp 'Man-bookmark-jump)
+ (Man-bookmark-jump bookmark) ; Emacs 24
+ (bmkp-jump-man bookmark)))
+
+(defun bmkp-jump-man (bookmark)
+ "Handler function for `man' page bookmark created by `man'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (require 'man)
+ (let* ((man-args (bookmark-prop-get bookmark 'man-args))
+ ;; `Man-notify-method' binding needs to be in effect during the calls to both
+ ;; `Man-getpage-in-background' and `accept-process-output'.
+ (Man-notify-method (case bmkp-jump-display-function
+ ((nil display-buffer) 'quiet)
+ (bmkp--pop-to-buffer-same-window 'pushy)
+ ((bmkp-select-buffer-other-window
+ switch-to-buffer-other-window
+ pop-to-buffer)
+ 'friendly)
+ (t 'quiet)))
+ (buf (Man-getpage-in-background man-args))
+ (proc (and (bufferp buf) ; Emacs 24+
+ (get-buffer-process buf))))
+ (if proc
+ (while (and proc (eq (process-status proc) 'run)) (accept-process-output proc))
+ (while (get-process "man") (sit-for 0.2)))
+ (bookmark-default-handler (bmkp-get-bookmark bookmark))))
+
+(defun bmkp-dired-remember-*-marks (beg end)
+ "Return a list of the files and subdirs marked `*' in Dired."
+ (if (fboundp 'dired--unhide) ; Emacs 27+ uses invisible text, not `selective-display'.
+ (with-silent-modifications (dired--unhide (point-min) (point-max)))
+ (when selective-display (let ((inhibit-read-only t)) (subst-char-in-region beg end ?\r ?\n))))
+ (let ((mfiles ())
+ fil)
+ (save-excursion (goto-char beg)
+ (while (re-search-forward "^\\*" end t) ; Not `dired-re-mark' - match only `*' marks.
+ (when (setq fil (dired-get-filename nil t)) (push fil mfiles))))
+ (nreverse mfiles)))
+
+(defun bmkp-make-dired-record ()
+ "Create and return a Dired bookmark record."
+ (let ((hidden-dirs (save-excursion (dired-remember-hidden))))
+ (unwind-protect
+ (let ((dir (expand-file-name (if (consp dired-directory)
+ (file-name-directory (car dired-directory))
+ dired-directory)))
+ (subdirs (bmkp-dired-subdirs))
+ (mfiles (bmkp-dired-remember-*-marks (point-min) (point-max))))
+ `(,dir
+ ,@(bookmark-make-record-default 'NO-FILE)
+ (filename . ,dir) (dired-directory . ,dired-directory)
+ (dired-marked . ,mfiles) (dired-switches . ,dired-actual-switches)
+ (dired-subdirs . ,subdirs) (dired-hidden-dirs . ,hidden-dirs)
+ (handler . bmkp-jump-dired)))
+ (save-excursion ; Hide subdirs that were hidden.
+ (dolist (dir hidden-dirs) (when (dired-goto-subdir dir) (dired-hide-subdir 1)))))))
+
+;;;###autoload (autoload 'bmkp-dired-subdirs "bookmark+")
+(defun bmkp-dired-subdirs ()
+ "Alist of inserted subdirectories, without their positions (markers).
+This is like `dired-subdir-alist' but without the top-level dir and
+without subdir positions (markers)."
+ (interactive)
+ (let ((subdir-alist (cdr (reverse dired-subdir-alist))) ; Remove top.
+ (subdirs-wo-posns ()))
+ (dolist (sub subdir-alist) (push (list (car sub)) subdirs-wo-posns))
+ subdirs-wo-posns))
+
+(add-hook 'dired-mode-hook (lambda () (set (make-local-variable 'bookmark-make-record-function)
+ 'bmkp-make-dired-record)))
+
+(defun bmkp-jump-dired (bookmark)
+ "Jump to Dired bookmark BOOKMARK.
+Handler function for record returned by `bmkp-make-dired-record'.
+BOOKMARK is a bookmark name or a bookmark record."
+ (let ((dir (bookmark-prop-get bookmark 'dired-directory))
+ (mfiles (bookmark-prop-get bookmark 'dired-marked))
+ (switches (bookmark-prop-get bookmark 'dired-switches))
+ (subdirs (bookmark-prop-get bookmark 'dired-subdirs))
+ (hidden-dirs (bookmark-prop-get bookmark 'dired-hidden-dirs)))
+ (case bmkp-jump-display-function
+ ((nil bmkp--pop-to-buffer-same-window display-buffer)
+ (dired dir switches))
+ ((bmkp-select-buffer-other-window pop-to-buffer switch-to-buffer-other-window)
+ (dired-other-window dir switches))
+ (t (dired dir switches)))
+ (let ((inhibit-read-only t))
+ (dired-insert-old-subdirs subdirs)
+ (dired-mark-remembered (mapcar (lexical-let ((dd dir))
+ (lambda (mf) (cons (expand-file-name mf dd) 42)))
+ mfiles))
+ (save-excursion (dolist (dir hidden-dirs) (when (dired-goto-subdir dir) (dired-hide-subdir 1)))))
+ (let ((pos (bookmark-get-position bookmark))) (when pos (goto-char pos)))))
+
+(defun bmkp-read-bookmark-for-type (type alist &optional other-win pred hist action prompt)
+ "Read name of a bookmark of type TYPE in ALIST, and return the bookmark.
+TYPE is a string used in the prompt: \"Jump to TYPE bookmark: \".
+ALIST is the alist used for completion. If nil then raise an error to
+ let the user know there are no bookmarks of type TYPE.
+Non-nil OTHER-WIN means append \" in another window\" to the prompt.
+Non-nil PRED is a predicate used for bookmark-name completion.
+Non-nil HIST is a history symbol. Default is `bookmark-history'.
+Non-nil ACTION is the action mentioned in the prompt; nil: `Jump to '.
+Non-nil PROMPT is an alternative prompt."
+ (unless alist (error "No bookmarks of type %s" type))
+ (bmkp-bookmark-record-from-name
+ (bookmark-completing-read (or prompt (concat (or action "Jump to ") type " bookmark"
+ (and other-win " in another window")))
+ (bmkp-default-bookmark-name alist)
+ alist pred hist)
+ 'NOERROR nil alist))
+
+;;;###autoload (autoload 'bmkp-jump-to-type "bookmark+")
+(defun bmkp-jump-to-type (bookmark &optional flip-use-region-p) ; `C-x j :'
+ "Jump to a bookmark of a given type. You are prompted for the type.
+Otherwise, this is the same as `bookmark-jump' - see that, in
+particular, for info about using a prefix argument.
+
+When prompted for the type, you can use completion against the known
+bookmark types (see function `bmkp-types-alist').
+
+Completion is lax, so you can also enter the name of a bookmark
+`handler' or `file-handler' function, without completion. Bookmarks
+with that entry value are then the jump candidates.
+
+When called from Lisp, BOOKMARK must be a bookmark record, not a
+bookmark name, or else an error is raised."
+ (interactive
+ (let* ((completion-ignore-case t)
+ (type-cands (bmkp-types-alist))
+ (icicle-unpropertize-completion-result-flag t)
+ (type (completing-read "Type of bookmark: " type-cands))
+ (history (assoc-default type type-cands))
+ (alist (if history
+ (funcall
+ (intern (format "bmkp-%s-alist-only" type)))
+ bookmark-alist))
+ (bmk (bmkp-read-bookmark-for-type
+ type alist nil
+ ;; PREDICATE if not a recognized type name.
+ (and (not history)
+ (bmkp-handler-pred (intern type)))
+ history)))
+ (list bmk (or (equal type "Region") current-prefix-arg))))
+ (when (stringp bookmark) (error "Not a bookmark record (perhaps a bookmark name): `%s'" bookmark))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-jump-to-type-other-window "bookmark+")
+(defun bmkp-jump-to-type-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j :'
+ "`bmkp-jump-to-type', but in another window."
+ (interactive
+ (let* ((completion-ignore-case t)
+ (type-cands (bmkp-types-alist))
+ (icicle-unpropertize-completion-result-flag t)
+ (type (completing-read "Type of bookmark: " type-cands))
+ (history (assoc-default type type-cands))
+ (alist (if history
+ (funcall
+ (intern (format "bmkp-%s-alist-only" type)))
+ bookmark-alist))
+ (bmk-name (bmkp-read-bookmark-for-type
+ type alist t
+ ;; PREDICATE if not a recognized type name.
+ (and (not history)
+ (bmkp-handler-pred (intern type)))
+ history)))
+ (list bmk-name (or (equal type "Region") current-prefix-arg))))
+ (when (stringp bookmark) (error "Not a bookmark record (perhaps a bookmark name): `%s'" bookmark))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+(defun bmkp-handler-pred (type)
+ "Return a bookmark predicate that tests bookmarks with handler TYPE.
+More precisely, the predicate returns non-nil if TYPE is either the
+bookmark's `handler' or `file-handler' entry value."
+ `(lambda (bmk)
+ (member ',type `(,(bookmark-prop-get bmk 'file-handler) ,(bookmark-get-handler bmk)))))
+
+;;;###autoload (autoload 'bmkp-autonamed-jump "bookmark+")
+(defun bmkp-autonamed-jump (bookmark) ; `C-x j #'
+ "Jump to an autonamed bookmark.
+This is a specialization of `bookmark-jump'."
+ (interactive
+ (let ((alist (bmkp-autonamed-alist-only)))
+ (list (bmkp-read-bookmark-for-type "autonamed" alist nil nil 'bmkp-autonamed-history))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-autonamed-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window))
+
+;;;###autoload (autoload 'bmkp-autonamed-jump-other-window "bookmark+")
+(defun bmkp-autonamed-jump-other-window (bookmark) ; `C-x 4 j # #'
+ "`bmkp-autonamed-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-autonamed-alist-only)))
+ (list (bmkp-read-bookmark-for-type "autonamed" alist t nil 'bmkp-autonamed-history))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-autonamed-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window))
+
+;;;###autoload (autoload 'bmkp-autonamed-this-buffer-jump "bookmark+")
+(defun bmkp-autonamed-this-buffer-jump (bookmark) ; `C-x j , #'
+ "Jump to an autonamed bookmark in the current buffer.
+This is a specialization of `bookmark-jump'."
+ (interactive
+ (let ((alist (bmkp-autonamed-this-buffer-alist-only)))
+ (list (bmkp-read-bookmark-for-type "autonamed" alist nil nil 'bmkp-autonamed-history))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-autonamed-this-buffer-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window))
+
+;;;###autoload (autoload 'bmkp-autonamed-this-buffer-jump-other-window "bookmark+")
+(defun bmkp-autonamed-this-buffer-jump-other-window (bookmark) ; `C-x 4 j # .'
+ "`bmkp-autonamed-this-buffer-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-autonamed-this-buffer-alist-only)))
+ (list (bmkp-read-bookmark-for-type "autonamed" alist t nil 'bmkp-autonamed-history))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-autonamed-this-buffer-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window))
+
+;;;###autoload (autoload 'bmkp-bookmark-list-jump "bookmark+")
+(defun bmkp-bookmark-list-jump (bookmark &optional flip-use-region-p) ; `C-x j B'
+ "Jump to a bookmark-list bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-bookmark-list-alist-only)))
+ (list (bmkp-read-bookmark-for-type "bookmark-list" alist nil nil 'bmkp-bookmark-list-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-bookmark-list-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-desktop-jump "bookmark+")
+(defun bmkp-desktop-jump (bookmark &optional flip-use-region-p) ; `C-x j K'
+ "Jump to a desktop bookmark.
+If option `bmkp-desktop-jump-save-before-flag' is non-nil, and if the
+current desktop was made current by jumping to a bookmark, then save
+it before jumping to the next desktop.
+
+This command is a specialization of `bookmark-jump' - see that, in
+particular for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-desktop-alist-only)))
+ (list (bmkp-read-bookmark-for-type "desktop" alist nil nil 'bmkp-desktop-history)
+ current-prefix-arg)))
+ (when bmkp-desktop-jump-save-before-flag (bmkp-desktop-save-as-last))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-desktop-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p)
+ (setq bmkp-desktop-current-file (bookmark-prop-get bookmark 'desktop-file)))
+
+;;;###autoload (autoload 'bmkp-dired-jump "bookmark+")
+(defun bmkp-dired-jump (bookmark &optional flip-use-region-p) ; `C-x j d', (`J' in Dired)
+ "Jump to a Dired bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-dired-alist-only)))
+ (list (bmkp-read-bookmark-for-type "Dired" alist nil nil 'bmkp-dired-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-dired-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-dired-jump-other-window "bookmark+")
+(defun bmkp-dired-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j d'
+ "`bmkp-dired-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-dired-alist-only)))
+ (list (bmkp-read-bookmark-for-type "Dired" alist t nil 'bmkp-dired-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-dired-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-dired-this-dir-jump "bookmark+")
+(defun bmkp-dired-this-dir-jump (bookmark &optional flip-use-region-p) ; `C-x j . d', (`C-j' in Dired)
+ "Jump to a Dired bookmark for the `default-directory'.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-dired-this-dir-alist-only)))
+ (list (bmkp-read-bookmark-for-type "Dired-for-this-dir " alist nil nil 'bmkp-dired-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-dired-this-dir-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-dired-this-dir-jump-other-window "bookmark+")
+(defun bmkp-dired-this-dir-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j C-d'
+ "`bmkp-dired-this-dir-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-dired-this-dir-alist-only)))
+ (list (bmkp-read-bookmark-for-type "Dired-for-this-dir" alist t nil 'bmkp-dired-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-dired-this-dir-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+(when (fboundp 'bmkp-eww-alist-only) ; Emacs 25+
+
+ ;; ;;;###autoload (autoload 'bmkp-eww-jump "bookmark+")
+ (defun bmkp-eww-jump (bookmark &optional flip-use-region-p) ; `C-x j e'
+ "Jump to an EWW bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-eww-alist-only)))
+ (list (bmkp-read-bookmark-for-type "EWW" alist nil nil 'bmkp-eww-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-eww-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+ ;; ;;;###autoload (autoload 'bmkp-eww-jump-other-window "bookmark+")
+ (defun bmkp-eww-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j e'
+ "`bmkp-eww-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-eww-alist-only)))
+ (list (bmkp-read-bookmark-for-type "EWW" alist t nil 'bmkp-eww-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-eww-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+ )
+
+;;;###autoload (autoload 'bmkp-file-jump "bookmark+")
+(defun bmkp-file-jump (bookmark &optional flip-use-region-p) ; `C-x j f'
+ "Jump to a file or directory bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "file" alist nil nil 'bmkp-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-file-jump-other-window "bookmark+")
+(defun bmkp-file-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j f'
+ "`bmkp-file-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "file" alist t nil 'bmkp-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-jump "bookmark+")
+(defun bmkp-file-this-dir-jump (bookmark &optional flip-use-region-p) ; `C-x j . f'
+ "Jump to a bookmark for a file or subdir in the `default-directory'.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-file-this-dir-alist-only)))
+ (list (bmkp-read-bookmark-for-type "file-in-this-dir" alist nil nil 'bmkp-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-file-this-dir-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-jump-other-window "bookmark+")
+(defun bmkp-file-this-dir-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j . f'
+ "`bmkp-file-this-dir-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-file-this-dir-alist-only)))
+ (list (bmkp-read-bookmark-for-type "file-in-this-dir" alist t nil 'bmkp-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-file-this-dir-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-gnus-jump "bookmark+")
+(defun bmkp-gnus-jump (bookmark &optional flip-use-region-p) ; `C-x j g', (`j' in Gnus summary mode)
+ "Jump to a Gnus bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-gnus-alist-only)))
+ (list (bmkp-read-bookmark-for-type "Gnus" alist nil nil 'bmkp-gnus-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-gnus-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-gnus-jump-other-window "bookmark+")
+(defun bmkp-gnus-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j g'
+ "`bmkp-gnus-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-gnus-alist-only)))
+ (list (bmkp-read-bookmark-for-type "Gnus" alist t nil 'bmkp-gnus-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-gnus-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-image-jump "bookmark+")
+(defun bmkp-image-jump (bookmark &optional flip-use-region-p) ; `C-x j M-i'
+ "Jump to an image-file bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-image-alist-only)))
+ (list (bmkp-read-bookmark-for-type "image" alist nil nil 'bmkp-image-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-image-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-image-jump-other-window "bookmark+")
+(defun bmkp-image-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x j M-i'
+ "`bmkp-image-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-image-alist-only)))
+ (list (bmkp-read-bookmark-for-type "image" alist t nil 'bmkp-image-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-image-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-info-jump "bookmark+")
+(defun bmkp-info-jump (bookmark &optional flip-use-region-p) ; `C-x j i', (`j' in Info)
+ "Jump to an Info bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-info-alist-only)))
+ (list (bmkp-read-bookmark-for-type "Info" alist nil nil 'bmkp-info-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-info-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-info-jump-other-window "bookmark+")
+(defun bmkp-info-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j i'
+ "`bmkp-info-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-info-alist-only)))
+ (list (bmkp-read-bookmark-for-type "Info" alist t nil 'bmkp-info-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-info-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-local-file-jump "bookmark+")
+(defun bmkp-local-file-jump (bookmark &optional flip-use-region-p) ; `C-x j l'
+ "Jump to a local file or directory bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-local-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "local file" alist nil nil 'bmkp-local-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-local-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-local-file-jump-other-window "bookmark+")
+(defun bmkp-local-file-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j l'
+ "`bmkp-local-file-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-local-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "local file" alist t nil 'bmkp-local-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-local-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-local-non-dir-file-jump "bookmark+")
+(defun bmkp-local-non-dir-file-jump (bookmark &optional flip-use-region-p) ; Not bound
+ "Jump to a local nondirectory file bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-local-non-dir-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "local non-dir file" alist nil nil 'bmkp-local-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-local-non-dir-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-local-non-dir-file-jump-other-window "bookmark+")
+(defun bmkp-local-non-dir-file-jump-other-window (bookmark &optional flip-use-region-p) ; Not bound
+ "`bmkp-local-non-dir-file-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-local-non-dir-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "local non-dir file" alist t nil 'bmkp-local-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-local-non-dir-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-man-jump "bookmark+")
+(defun bmkp-man-jump (bookmark &optional flip-use-region-p) ; `C-x j m', (`j' in Man)
+ "Jump to a `man'-page bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-man-alist-only)))
+ (list (bmkp-read-bookmark-for-type "`man'" alist nil nil 'bmkp-man-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-man-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-man-jump-other-window "bookmark+")
+(defun bmkp-man-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j m'
+ "`bmkp-man-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-man-alist-only)))
+ (list (bmkp-read-bookmark-for-type "`man'" alist t nil 'bmkp-man-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-man-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-non-dir-file-jump "bookmark+")
+(defun bmkp-non-dir-file-jump (bookmark &optional flip-use-region-p) ; Not bound
+ "Jump to a nondirectory file bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-non-dir-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "non-dir file" alist nil nil 'bmkp-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-non-dir-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-non-dir-file-jump-other-window "bookmark+")
+(defun bmkp-non-dir-file-jump-other-window (bookmark &optional flip-use-region-p) ; Not bound
+ "`bmkp-non-dir-file-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-non-dir-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "non-dir file" alist t nil 'bmkp-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-non-dir-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-non-file-jump "bookmark+")
+(defun bmkp-non-file-jump (bookmark &optional flip-use-region-p) ; `C-x j b', (`j' in Buffer Menu)
+ "Jump to a non-file (buffer) bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-non-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "non-file (buffer)" alist nil nil 'bmkp-non-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-non-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-non-file-jump-other-window "bookmark+")
+(defun bmkp-non-file-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j b'
+ "`bmkp-non-file-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-non-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "non-file (buffer)" alist t nil 'bmkp-non-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-non-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-region-jump "bookmark+")
+(defun bmkp-region-jump (bookmark) ; `C-x j r'
+ "Jump to a region bookmark. Select the region.
+This is a specialization of `bookmark-jump', but without a prefix arg.
+BOOKMARK is a bookmark name or a bookmark record."
+ (interactive (list (bmkp-read-bookmark-for-type "region" (bmkp-region-alist-only) nil nil
+ 'bmkp-region-history)))
+ (let ((bmkp-use-region t)) (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window)))
+
+;;;###autoload (autoload 'bmkp-region-jump-other-window "bookmark+")
+(defun bmkp-region-jump-other-window (bookmark) ; `C-x 4 j r'
+ "`bmkp-region-jump', but in another window."
+ (interactive (list (bmkp-read-bookmark-for-type "region" (bmkp-region-alist-only) t nil
+ 'bmkp-region-history)))
+ (let ((bmkp-use-region t)) (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window)))
+
+;; This command accepts no argument. It calls another command interactively, which reads the bookmark name.
+;;
+;;;###autoload (autoload 'bmkp-region-jump-narrow-indirect-other-window "bookmark+")
+(defun bmkp-region-jump-narrow-indirect-other-window ()
+ "Jump to a region bookmark and narrow to it in a cloned indirect buffer.
+You are prompted for the region bookmark.
+
+The region is selected as usual, in the bookmarked file/buffer. A
+separate window is opened on the region text, for the cloned indirect
+buffer.
+
+You need library `narrow-indirect.el' to use this command."
+ (interactive)
+ (unless (require 'narrow-indirect nil t)
+ (error "You need library `narrow-indirect.el' for this command"))
+ (let ((bmkp-handle-region-function 'bmkp-handle-region+narrow-indirect))
+ (call-interactively
+ (if (and (boundp 'icicle-mode) icicle-mode) ; Icicles
+ #'icicle-bookmark-region-other-window
+ #'bmkp-region-jump-other-window))))
+
+(defun bmkp-handle-region+narrow-indirect (bookmark)
+ "`bmkp-handle-region-default', then narrow to region in cloned buffer."
+ (let ((bmkp-handle-region-function 'bmkp-handle-region-default))
+ (bookmark-handle-bookmark bookmark))
+ (if (get major-mode 'no-clone-indirect) ; e.g., `Info-mode'
+ (message "Cannot indirectly clone a buffer in `%s' mode" major-mode)
+ (ni-narrow-to-region-indirect-other-window (region-beginning) (region-end) (point))))
+
+;;;###autoload (autoload 'bmkp-remote-file-jump "bookmark+")
+(defun bmkp-remote-file-jump (bookmark &optional flip-use-region-p) ; `C-x j n'
+ "Jump to a remote file or directory bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-remote-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "remote file" alist nil nil 'bmkp-remote-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-remote-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-remote-file-jump-other-window "bookmark+")
+(defun bmkp-remote-file-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j n'
+ "`bmkp-remote-file-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-remote-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "remote file" alist t nil 'bmkp-remote-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-remote-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-remote-non-dir-file-jump "bookmark+")
+(defun bmkp-remote-non-dir-file-jump (bookmark &optional flip-use-region-p) ; Not bound
+ "Jump to a remote nondirectory file bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-remote-non-dir-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "remote non-dir file" alist nil nil 'bmkp-remote-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-remote-non-dir-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-remote-non-dir-file-jump-other-window "bookmark+")
+(defun bmkp-remote-non-dir-file-jump-other-window (bookmark &optional flip-use-region-p) ; Not bound
+ "`bmkp-remote-non-dir-file-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-remote-non-dir-file-alist-only)))
+ (list (bmkp-read-bookmark-for-type "remote non-dir file" alist t nil 'bmkp-remote-file-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-remote-non-dir-file-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-specific-buffers-jump "bookmark+")
+(defun bmkp-specific-buffers-jump (buffers bookmark &optional flip-use-region-p) ; `C-x j = b'
+ "Jump to a bookmark for a buffer in list BUFFERS.
+Interactively, read buffer names and bookmark name, with completion.
+
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let* ((buffs (bmkp-read-buffers))
+ (alist (bmkp-specific-buffers-alist-only buffs)))
+ (list buffs (bmkp-read-bookmark-for-type "specific-buffers" alist nil nil 'specific-buffers-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-specific-buffers-alist-only buffers))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-specific-buffers-jump-other-window "bookmark+")
+(defun bmkp-specific-buffers-jump-other-window (buffers bookmark
+ &optional flip-use-region-p) ; `C-x 4 j = b'
+ "`bmkp-specific-buffers-jump', but in another window."
+ (interactive
+ (let* ((buffs (bmkp-read-buffers))
+ (alist (bmkp-specific-buffers-alist-only buffs)))
+ (list buffs (bmkp-read-bookmark-for-type "specific-buffers" alist t nil 'specific-buffers-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-specific-buffers-alist-only buffers))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-specific-files-jump "bookmark+")
+(defun bmkp-specific-files-jump (files bookmark &optional flip-use-region-p) ; `C-x j = f'
+ "Jump to a bookmark for a file in list FILES.
+Interactively, read file names and bookmark name, with completion.
+
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let* ((fils (bmkp-read-files))
+ (alist (bmkp-specific-files-alist-only fils)))
+ (list fils
+ (bmkp-read-bookmark-for-type "specific-files" alist nil nil 'specific-files-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-specific-files-alist-only files))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-specific-files-jump-other-window "bookmark+")
+(defun bmkp-specific-files-jump-other-window (files bookmark
+ &optional flip-use-region-p) ; `C-x 4 j = f'
+ "`bmkp-specific-files-jump', but in another window."
+ (interactive
+ (let* ((fils (bmkp-read-files))
+ (alist (bmkp-specific-files-alist-only fils)))
+ (list fils
+ (bmkp-read-bookmark-for-type "specific-files" alist t nil 'specific-files-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-specific-files-alist-only files))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-temporary-jump "bookmark+")
+(defun bmkp-temporary-jump (bookmark) ; `C-x j x'
+ "Jump to a temporary bookmark.
+This is a specialization of `bookmark-jump', but without a prefix arg."
+ (interactive (list (bmkp-read-bookmark-for-type "temporary" (bmkp-temporary-alist-only) nil nil
+ 'bmkp-temporary-history)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-temporary-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window))
+
+;;;###autoload (autoload 'bmkp-temporary-jump-other-window "bookmark+")
+(defun bmkp-temporary-jump-other-window (bookmark) ; `C-x 4 j x'
+ "`bmkp-temporary-jump', but in another window."
+ (interactive (list (bmkp-read-bookmark-for-type "temporary" (bmkp-temporary-alist-only) t nil
+ 'bmkp-temporary-history)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-temporary-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window))
+
+;;;###autoload (autoload 'bmkp-this-buffer-jump "bookmark+")
+(defun bmkp-this-buffer-jump (bookmark &optional flip-use-region-p) ; `C-x j , ,'
+ "Jump to a bookmark for the current buffer.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-this-buffer-alist-only)))
+ (unless alist (error "No bookmarks for this buffer"))
+ (list (bookmark-completing-read "Jump to bookmark for this buffer"
+ (bmkp-default-bookmark-name alist) alist)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-this-buffer-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-this-buffer-jump-other-window "bookmark+")
+(defun bmkp-this-buffer-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j , ,'
+ "`bmkp-this-buffer-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-this-buffer-alist-only)))
+ (unless alist (error "No bookmarks for this buffer"))
+ (list (bookmark-completing-read "Jump to bookmark for this buffer in another window"
+ (bmkp-default-bookmark-name alist) alist)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-this-buffer-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;; ;;;###autoload
+;;; (defun bmkp-this-file-jump (bookmark-name &optional flip-use-region-p)
+;;; "Jump to a bookmark for the current file (absolute file name).
+;;; This is a specialization of `bookmark-jump' - see that, in particular
+;;; for info about using a prefix argument."
+;;; (interactive
+;;; (progn (unless (or (buffer-file-name) (and (eq major-mode 'dired-mode)
+;;; (if (consp dired-directory)
+;;; (car dired-directory)
+;;; dired-directory)))
+;;; (error "This buffer is not associated with a file"))
+;;; (let ((alist (bmkp-this-file-alist-only)))
+;;; (unless alist (error "No bookmarks for this file"))
+;;; (list (bookmark-completing-read "Jump to bookmark for this file"
+;;; (bmkp-default-bookmark-name alist) alist)
+;;; current-prefix-arg))))
+;;; (bmkp-jump-1 bookmark-name 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;; ;;;###autoload
+;;; (defun bmkp-this-file-jump-other-window (bookmark-name &optional flip-use-region-p)
+;;; "`bmkp-this-file-jump', but in another window."
+;;; (interactive
+;;; (progn (unless (or (buffer-file-name) (and (eq major-mode 'dired-mode)
+;;; (if (consp dired-directory)
+;;; (car dired-directory)
+;;; dired-directory)))
+;;; (error "This buffer is not associated with a file"))
+;;; (let ((alist (bmkp-this-file-alist-only)))
+;;; (unless alist (error "No bookmarks for this file"))
+;;; (list (bookmark-completing-read "Jump to bookmark for this file in another window"
+;;; (bmkp-default-bookmark-name alist) alist)
+;;; current-prefix-arg))))
+;;; (bmkp-jump-1 bookmark-name 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-variable-list-jump "bookmark+")
+(defun bmkp-variable-list-jump (bookmark) ; `C-x j v'
+ "Jump to a variable-list bookmark.
+This is a specialization of `bookmark-jump'."
+ (interactive
+ (let ((alist (bmkp-variable-list-alist-only)))
+ (list (bmkp-read-bookmark-for-type "variable-list" alist nil nil 'bmkp-variable-list-history))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-variable-list-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window))
+
+;;;###autoload (autoload 'bmkp-url-jump "bookmark+")
+(defun bmkp-url-jump (bookmark &optional flip-use-region-p) ; `C-x j u'
+ "Jump to a URL bookmark.
+It can be an EWW bookmark, a W3M bookmark, or a browse-URL bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-url-alist-only)))
+ (list (bmkp-read-bookmark-for-type "URL" alist nil nil 'bmkp-url-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-url-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-url-jump-other-window "bookmark+")
+(defun bmkp-url-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j u'
+ "`bmkp-url-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-url-alist-only)))
+ (list (bmkp-read-bookmark-for-type "URL" alist t nil 'bmkp-url-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-url-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-w32-browser-jump "bookmark+")
+(defun bmkp-w32-browser-jump (bookmark) ; Not bound
+ "Jump to a bookmark whose handler applies `w32-browser' to its file.
+This is a specialization of `bookmark-jump'."
+ (interactive
+ (list (bmkp-read-bookmark-for-type "w32-browser" bookmark-alist nil
+ ;; Use a predicate, since `w32-browser' is a handler, not a type name.
+ (bmkp-handler-pred 'w32-browser)
+ 'bmkp-w32-browser-history)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR)))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window))
+
+;;;###autoload (autoload 'bmkp-w3m-jump "bookmark+")
+(defun bmkp-w3m-jump (bookmark &optional flip-use-region-p) ; `C-x j w', (`j' in W3M)
+ "Jump to a W3M bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-w3m-alist-only)))
+ (list (bmkp-read-bookmark-for-type "W3M" alist nil nil 'bmkp-w3m-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-w3m-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-w3m-jump-other-window "bookmark+")
+(defun bmkp-w3m-jump-other-window (bookmark &optional flip-use-region-p) ; `C-x 4 j w'
+ "`bmkp-w3m-jump', but in another window."
+ (interactive
+ (let ((alist (bmkp-w3m-alist-only)))
+ (list (bmkp-read-bookmark-for-type "W3M" alist t nil 'bmkp-w3m-history)
+ current-prefix-arg)))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-w3m-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-all-tags-jump "bookmark+")
+(defun bmkp-all-tags-jump (tags bookmark) ; `C-x j t *'
+ "Jump to a BOOKMARK that has all of the TAGS.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+If you specify no tags, then every bookmark that has some tags is a
+candidate.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-all-tags-alist-only tgs)))
+ (unless alist (error "No bookmarks have all of the specified tags"))
+ (list tgs (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-all-tags-jump-other-window "bookmark+")
+(defun bmkp-all-tags-jump-other-window (tags bookmark) ; `C-x 4 j t *'
+ "`bmkp-all-tags-jump', but in another window."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-all-tags-alist-only tgs)))
+ (unless alist (error "No bookmarks have all of the specified tags"))
+ (list tgs (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-all-tags-regexp-jump "bookmark+")
+(defun bmkp-all-tags-regexp-jump (regexp bookmark) ; `C-x j t % *'
+ "Jump to a BOOKMARK that has each tag matching REGEXP.
+You are prompted for the REGEXP.
+Then you are prompted for the BOOKMARK (with completion)."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for all tags: "))
+ (alist (bmkp-all-tags-regexp-alist-only rgx)))
+ (unless alist (error "No bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-all-tags-regexp-jump-other-window "bookmark+")
+(defun bmkp-all-tags-regexp-jump-other-window (regexp bookmark) ; `C-x 4 j t % *'
+ "`bmkp-all-tags-regexp-jump', but in another window."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for all tags: "))
+ (alist (bmkp-all-tags-regexp-alist-only rgx)))
+ (unless alist (error "No bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-some-tags-jump "bookmark+")
+(defun bmkp-some-tags-jump (tags bookmark) ; `C-x j t +'
+ "Jump to a BOOKMARK that has at least one of the TAGS.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-some-tags-alist-only tgs)))
+ (unless tgs (error "You did not specify any tags"))
+ (unless alist (error "No bookmarks have any of the specified tags"))
+ (list tgs (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-some-tags-jump-other-window "bookmark+")
+(defun bmkp-some-tags-jump-other-window (tags bookmark) ; `C-x 4 j t +'
+ "`bmkp-some-tags-jump', but in another window."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-some-tags-alist-only tgs)))
+ (unless tgs (error "You did not specify any tags"))
+ (unless alist (error "No bookmarks have any of the specified tags"))
+ (list tgs (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-some-tags-regexp-jump "bookmark+")
+(defun bmkp-some-tags-regexp-jump (regexp bookmark) ; `C-x j t % +'
+ "Jump to a BOOKMARK that has a tag matching REGEXP.
+You are prompted for the REGEXP.
+Then you are prompted for the BOOKMARK (with completion)."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-some-tags-regexp-alist-only rgx)))
+ (unless alist (error "No bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-some-tags-regexp-jump-other-window "bookmark+")
+(defun bmkp-some-tags-regexp-jump-other-window (regexp bookmark) ; `C-x 4 j t % +'
+ "`bmkp-some-tags-regexp-jump', but in another window."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-some-tags-regexp-alist-only rgx)))
+ (unless alist (error "No bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-file-all-tags-jump "bookmark+")
+(defun bmkp-file-all-tags-jump (tags bookmark) ; `C-x j t f *'
+ "Jump to a file or directory BOOKMARK that has all of the TAGS.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+If you specify no tags, then every bookmark that has some tags is a
+candidate.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-file-all-tags-alist-only tgs)))
+ (unless alist (error "No file or dir bookmarks have all of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-file-all-tags-jump-other-window "bookmark+")
+(defun bmkp-file-all-tags-jump-other-window (tags bookmark) ; `C-x 4 j t f *'
+ "`bmkp-file-all-tags-jump', but in another window."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-file-all-tags-alist-only tgs)))
+ (unless alist (error "No file or dir bookmarks have all of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-file-all-tags-regexp-jump "bookmark+")
+(defun bmkp-file-all-tags-regexp-jump (regexp bookmark) ; `C-x j t f % *'
+ "Jump to a file or directory BOOKMARK that has each tag matching REGEXP.
+You are prompted for the REGEXP.
+Then you are prompted for the BOOKMARK (with completion)."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-file-all-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-file-all-tags-regexp-jump-other-window "bookmark+")
+(defun bmkp-file-all-tags-regexp-jump-other-window (regexp bookmark) ; `C-x 4 j t f % *'
+ "`bmkp-file-all-tags-regexp-jump', but in another window."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-file-all-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-file-some-tags-jump "bookmark+")
+(defun bmkp-file-some-tags-jump (tags bookmark) ; `C-x j t f +'
+ "Jump to a file or directory BOOKMARK that has at least one of the TAGS.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-file-some-tags-alist-only tgs)))
+ (unless tgs (error "You did not specify any tags"))
+ (unless alist (error "No file or dir bookmarks have any of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-file-some-tags-jump-other-window "bookmark+")
+(defun bmkp-file-some-tags-jump-other-window (tags bookmark) ; `C-x 4 j t f +'
+ "`bmkp-file-some-tags-jump', but in another window."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-file-some-tags-alist-only tgs)))
+ (unless tgs (error "You did not specify any tags"))
+ (unless alist (error "No file or dir bookmarks have any of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-file-some-tags-regexp-jump "bookmark+")
+(defun bmkp-file-some-tags-regexp-jump (regexp bookmark) ; `C-x j t f % +'
+ "Jump to a file or directory BOOKMARK that has a tag matching REGEXP.
+You are prompted for the REGEXP.
+Then you are prompted for the BOOKMARK (with completion)."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-file-some-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-file-some-tags-regexp-jump-other-window "bookmark+")
+(defun bmkp-file-some-tags-regexp-jump-other-window (regexp bookmark) ; `C-x 4 j t f % +'
+ "`bmkp-file-some-tags-regexp-jump', but in another window."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-file-some-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-all-tags-jump "bookmark+")
+(defun bmkp-file-this-dir-all-tags-jump (tags bookmark) ; `C-x j t . *'
+ "Jump to a file BOOKMARK in this dir that has all of the TAGS.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+If you specify no tags, then every bookmark that has some tags is a
+candidate.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-file-this-dir-all-tags-alist-only tgs)))
+ (unless alist (error "No file or dir bookmarks have all of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-all-tags-jump-other-window "bookmark+")
+(defun bmkp-file-this-dir-all-tags-jump-other-window (tags bookmark) ; `C-x 4 j t . *'
+ "`bmkp-file-this-dir-all-tags-jump', but in another window."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-file-this-dir-all-tags-alist-only tgs)))
+ (unless alist (error "No file or dir bookmarks have all of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-all-tags-regexp-jump "bookmark+")
+(defun bmkp-file-this-dir-all-tags-regexp-jump (regexp bookmark) ; `C-x j t . % *'
+ "Jump to a file BOOKMARK in this dir that has each tag matching REGEXP.
+You are prompted for the REGEXP.
+Then you are prompted for the BOOKMARK (with completion)."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-file-this-dir-all-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-all-tags-regexp-jump-other-window "bookmark+")
+(defun bmkp-file-this-dir-all-tags-regexp-jump-other-window (regexp bookmark) ; `C-x 4 j t . % *'
+ "`bmkp-file-this-dir-all-tags-regexp-jump', but in another window."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-file-this-dir-all-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-some-tags-jump "bookmark+")
+(defun bmkp-file-this-dir-some-tags-jump (tags bookmark) ; `C-x j t . +'
+ "Jump to a file BOOKMARK in this dir that has at least one of the TAGS.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-file-this-dir-some-tags-alist-only tgs)))
+ (unless tgs (error "You did not specify any tags"))
+ (unless alist (error "No file or dir bookmarks have any of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-some-tags-jump-other-window "bookmark+")
+(defun bmkp-file-this-dir-some-tags-jump-other-window (tags bookmark) ; `C-x 4 j t . +'
+ "`bmkp-file-this-dir-some-tags-jump', but in another window."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-file-this-dir-some-tags-alist-only tgs)))
+ (unless tgs (error "You did not specify any tags"))
+ (unless alist (error "No file or dir bookmarks have any of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-some-tags-regexp-jump "bookmark+")
+(defun bmkp-file-this-dir-some-tags-regexp-jump (regexp bookmark) ; `C-x j t . % +'
+ "Jump to a file BOOKMARK in this dir that has a tag matching REGEXP.
+You are prompted for the REGEXP.
+Then you are prompted for the BOOKMARK (with completion)."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-file-this-dir-some-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-file-this-dir-some-tags-regexp-jump-other-window "bookmark+")
+(defun bmkp-file-this-dir-some-tags-regexp-jump-other-window (regexp bookmark) ; `C-x 4 j t . % +'
+ "`bmkp-file-this-dir-some-tags-regexp-jump', but in another window."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-file-this-dir-some-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-autofile-jump "bookmark+")
+(defun bmkp-autofile-jump (bookmark) ; `C-x j a'
+ "Jump to an autofile bookmark.
+This is a specialization of `bookmark-jump'."
+ (interactive
+ (let ((alist (bmkp-autofile-alist-only)))
+ (list (bmkp-read-bookmark-for-type "autofile" alist nil nil 'bmkp-autofile-history))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-autofile-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp--pop-to-buffer-same-window))
+
+;;;###autoload (autoload 'bmkp-autofile-jump-other-window "bookmark+")
+(defun bmkp-autofile-jump-other-window (bookmark) ; `C-x 4 j a'
+ "`bmkp-autofile-jump' but in another window."
+ (interactive
+ (let ((alist (bmkp-autofile-alist-only)))
+ (list (bmkp-read-bookmark-for-type "autofile" alist t nil 'bmkp-autofile-history))))
+ (when (stringp bookmark)
+ (setq bookmark (bmkp-get-bookmark-in-alist bookmark 'NOERROR (bmkp-autofile-alist-only))))
+ (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window))
+
+;;;###autoload (autoload 'bmkp-autofile-all-tags-jump "bookmark+")
+(defun bmkp-autofile-all-tags-jump (tags bookmark) ; `C-x j t a *'
+ "Jump to an autofile BOOKMARK in this dir that has all of the TAGS.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+If you specify no tags, then every bookmark that has some tags is a
+candidate.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-autofile-all-tags-alist-only tgs)))
+ (unless alist (error "No file or dir bookmarks have all of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-autofile-all-tags-jump-other-window "bookmark+")
+(defun bmkp-autofile-all-tags-jump-other-window (tags bookmark) ; `C-x 4 j t a *'
+ "`bmkp-autofile-all-tags-jump', but in another window."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-autofile-all-tags-alist-only tgs)))
+ (unless alist (error "No file or dir bookmarks have all of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-autofile-all-tags-regexp-jump "bookmark+")
+(defun bmkp-autofile-all-tags-regexp-jump (regexp bookmark) ; `C-x j t a % *'
+ "Jump to an autofile BOOKMARK in this dir that has each tag matching REGEXP.
+You are prompted for the REGEXP.
+Then you are prompted for the BOOKMARK (with completion)."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-autofile-all-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-autofile-all-tags-regexp-jump-other-window "bookmark+")
+(defun bmkp-autofile-all-tags-regexp-jump-other-window (regexp bookmark) ; `C-x 4 j t a % *'
+ "`bmkp-autofile-all-tags-regexp-jump', but in another window."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-autofile-all-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-autofile-some-tags-jump "bookmark+")
+(defun bmkp-autofile-some-tags-jump (tags bookmark) ; `C-x j t a +'
+ "Jump to an autofile BOOKMARK in this dir that has at least one of the TAGS.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter the bookmark name and each tag.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-autofile-some-tags-alist-only tgs)))
+ (unless tgs (error "You did not specify any tags"))
+ (unless alist (error "No file or dir bookmarks have any of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-autofile-some-tags-jump-other-window "bookmark+")
+(defun bmkp-autofile-some-tags-jump-other-window (tags bookmark) ; `C-x 4 j t a +'
+ "`bmkp-autofile-some-tags-jump', but in another window."
+ (interactive
+ (let* ((tgs (bmkp-read-tags-completing nil nil current-prefix-arg))
+ (alist (bmkp-autofile-some-tags-alist-only tgs)))
+ (unless tgs (error "You did not specify any tags"))
+ (unless alist (error "No file or dir bookmarks have any of the specified tags"))
+ (list tgs (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+;;;###autoload (autoload 'bmkp-autofile-some-tags-regexp-jump "bookmark+")
+(defun bmkp-autofile-some-tags-regexp-jump (regexp bookmark) ; `C-x j t a % +'
+ "Jump to an autofile BOOKMARK in this dir that has a tag matching REGEXP.
+You are prompted for the REGEXP.
+Then you are prompted for the BOOKMARK (with completion)."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-autofile-some-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump bookmark))
+
+;;;###autoload (autoload 'bmkp-autofile-some-tags-regexp-jump-other-window "bookmark+")
+(defun bmkp-autofile-some-tags-regexp-jump-other-window (regexp bookmark) ; `C-x 4 j t a % +'
+ "`bmkp-autofile-some-tags-regexp-jump', but in another window."
+ (interactive
+ (let* ((rgx (bmkp-read-regexp "Regexp for tags: "))
+ (alist (bmkp-autofile-some-tags-regexp-alist-only rgx)))
+ (unless alist (error "No file or dir bookmarks have tags that match `%s'" rgx))
+ (list rgx (bookmark-completing-read "File bookmark" (bmkp-default-bookmark-name alist) alist))))
+ (bookmark-jump-other-window bookmark))
+
+(defun bmkp-find-file (&optional file create-autofile-p must-exist-p msg-p) ; `C-x j C-f'
+ "Visit a file or directory, respecting any associated autofile handlers.
+You are prompted for the file or directory name, FILE.
+
+If FILE matches an entry in `bmkp-default-handlers-for-file-types'
+then use the associated default handler to access the file.
+Otherwise, just use `find-file'.
+
+With a prefix arg, create an autofile bookmark if FILE does not
+already have one.
+
+Non-interactively:
+* Non-nil MUST-EXIST-P means raise an error if FILE has no autofile
+ bookmark.
+* Non-nil MSG-P means display a status message."
+ (interactive "i\nP\ni\np")
+ (let* ((use-file-dialog nil)
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (fil (or file (read-file-name "Find file: " nil nil t)))
+ (dir-to-use (if (file-name-absolute-p fil)
+ (file-name-directory fil)
+ default-directory))
+ (bmk (bmkp-get-autofile-bookmark fil)))
+ (if bmk
+ (bookmark-jump bmk)
+ (when must-exist-p (error "File `%s' is not an autofile (no bookmark)" fil))
+ (when create-autofile-p ; Create a new bookmark.
+ (bmkp-file-target-set (expand-file-name fil dir-to-use) t nil 'NO-OVERWRITE msg-p)
+ (when msg-p (message "Autofile bookmark set for `%s'" fil)))
+ (let ((default-handler (condition-case nil (bmkp-default-handler-for-file fil) (error nil))))
+ (if default-handler (funcall default-handler fil) (find-file fil 'WILDCARDS))))))
+
+(defun bmkp-find-file-other-window (&optional file create-autofile-p must-exist-p msg-p) ; `C-x 4 j C-f'
+ "`bmkp-find-file', but in another window."
+ (interactive "i\nP\ni\np")
+ (let* ((use-file-dialog nil)
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (fil (or file (read-file-name "Find file: " nil nil t)))
+ (dir-to-use (if (file-name-absolute-p fil)
+ (file-name-directory fil)
+ default-directory))
+ (bmk (bmkp-get-autofile-bookmark fil dir-to-use)))
+ (if bmk
+ (bookmark-jump-other-window bmk)
+ (when must-exist-p (error "File `%s' is not an autofile (no bookmark)" fil))
+ (when create-autofile-p ; Create a new bookmark.
+ (bmkp-file-target-set (expand-file-name fil dir-to-use) t nil 'NO-OVERWRITE msg-p)
+ (when msg-p (message "Autofile bookmark created for `%s'" fil)))
+ (let ((default-handler (condition-case nil (bmkp-default-handler-for-file fil) (error nil))))
+ (if default-handler (funcall default-handler fil) (find-file-other-window fil 'WILDCARDS))))))
+
+
+;;; We could allow these even for Emacs 20 for Icicles users,
+;;; but the predicate would have no effect when not in Icicle mode. So don't bother with Emacs 20.
+
+(when (> emacs-major-version 21) ; Needs `read-file-name' with a PREDICATE arg.
+ (defun bmkp-find-file-all-tags (tags &optional file) ; `C-x j t C-f *'
+ "Visit a file or directory that has all of the TAGS.
+You are prompted first for the tags. Hit `RET' to enter each tag,
+then hit `RET' again after the last tag. You can use completion to
+enter each tag. This completion is lax: you are not limited to
+existing tags.
+
+You are then prompted for the file name. This is read using
+`read-file-name', so you can browse up and down the file hierarchy.
+The completion candidates are file names, not bookmark names.
+However, only files that are bookmarked as autofiles are candidates.
+
+If you specify no tags, then every file that has some tags is a
+candidate.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive (list (bmkp-read-tags-completing nil nil current-prefix-arg)))
+ (lexical-let* ((tgs tags)
+ (use-file-dialog nil)
+ (pred
+ (lambda (ff)
+ (lexical-let* ((bmk (bmkp-get-autofile-bookmark ff))
+ (btgs (and bmk (bmkp-get-tags bmk))))
+ (and btgs (bmkp-every (lambda (tag) (bmkp-has-tag-p bmk tag)) tgs)))))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (icicle-must-pass-after-match-predicate pred)
+ (fil (or (and file (funcall pred file) file)
+ (read-file-name
+ "Find file: " nil nil t nil
+ (and (or (not (boundp 'icicle-mode))
+ (not icicle-mode))
+ pred))))
+ (bmk (bmkp-get-autofile-bookmark fil)))
+ (when bmk (bookmark-jump bmk)))))
+
+(when (> emacs-major-version 21) ; Needs `read-file-name' with a PREDICATE arg.
+ (defun bmkp-find-file-all-tags-other-window (tags &optional file) ; `C-x 4 j t C-f *'
+ "`bmkp-find-file-all-tags', but in another window."
+ (interactive (list (bmkp-read-tags-completing nil nil current-prefix-arg)))
+ (lexical-let* ((tgs tags)
+ (use-file-dialog nil)
+ (pred
+ (lambda (ff)
+ (lexical-let* ((bk (bmkp-get-autofile-bookmark ff))
+ (btgs (and bk (bmkp-get-tags bk))))
+ (and btgs (bmkp-every (lambda (tag) (bmkp-has-tag-p bk tag)) tgs)))))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (icicle-must-pass-after-match-predicate pred)
+ (fil (or (and file (funcall pred file) file)
+ (read-file-name
+ "Find file: " nil nil t nil
+ (and (or (not (boundp 'icicle-mode))
+ (not icicle-mode))
+ pred))))
+ (bmk (bmkp-get-autofile-bookmark fil)))
+ (bookmark-jump-other-window bmk))))
+
+(when (> emacs-major-version 21) ; Needs `read-file-name' with a PREDICATE arg.
+ (defun bmkp-find-file-all-tags-regexp (regexp &optional file) ; `C-x j t C-f % *'
+ "Visit a file or directory that has each tag matching REGEXP.
+You are prompted for the REGEXP."
+ (interactive (list (bmkp-read-regexp "Regexp for tags: ")))
+ (lexical-let* ((rg regexp)
+ (use-file-dialog nil)
+ (pred
+ (lambda (ff)
+ (let* ((bk (bmkp-get-autofile-bookmark ff))
+ (btgs (and bk (bmkp-get-tags bk))))
+ (and btgs (bmkp-every (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag)))
+ btgs)))))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (icicle-must-pass-after-match-predicate pred)
+ (fil (or (and file (funcall pred file) file)
+ (read-file-name
+ "Find file: " nil nil t nil
+ (and (or (not (boundp 'icicle-mode))
+ (not icicle-mode))
+ pred))))
+ (bmk (bmkp-get-autofile-bookmark fil)))
+ (bookmark-jump bmk))))
+
+;;;###autoload (autoload 'bmkp-find-file-all-tags-regexp-other-window "bookmark+")
+(when (> emacs-major-version 21) ; Needs `read-file-name' with a PREDICATE arg.
+ (defun bmkp-find-file-all-tags-regexp-other-window (regexp &optional file) ; `C-x 4 j t C-f % *'
+ "`bmkp-find-file-all-tags-regexp', but in another window."
+ (interactive (list (bmkp-read-regexp "Regexp for tags: ")))
+ (lexical-let* ((rg regexp)
+ (use-file-dialog nil)
+ (pred
+ (lambda (ff)
+ (let* ((bk (bmkp-get-autofile-bookmark ff))
+ (btgs (and bk (bmkp-get-tags bk))))
+ (and btgs (bmkp-every (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag)))
+ btgs)))))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (icicle-must-pass-after-match-predicate pred)
+ (fil (or (and file (funcall pred file) file)
+ (read-file-name
+ "Find file: " nil nil t nil
+ (and (or (not (boundp 'icicle-mode))
+ (not icicle-mode))
+ pred))))
+ (bmk (bmkp-get-autofile-bookmark fil)))
+ (bookmark-jump-other-window bmk))))
+
+;;;###autoload (autoload 'bmkp-find-file-some-tags "bookmark+")
+(when (> emacs-major-version 21) ; Needs `read-file-name' with a PREDICATE arg.
+ (defun bmkp-find-file-some-tags (tags &optional file) ; `C-x j t C-f +'
+ "Visit a file or directory that has at least one of the TAGS.
+You are prompted first for the tags. Hit `RET' to enter each tag,
+then hit `RET' again after the last tag. You can use completion to
+enter each tag. This completion is lax: you are not limited to
+existing tags.
+
+You are then prompted for the file name. This is read using
+`read-file-name', so you can browse up and down the file hierarchy.
+The completion candidates are file names, not bookmark names.
+However, only files that are bookmarked as autofiles are candidates.
+
+By default, the tag choices for completion are NOT refreshed, to save
+time. Use a prefix argument if you want to refresh them."
+ (interactive (list (bmkp-read-tags-completing nil nil current-prefix-arg)))
+ (lexical-let* ((tgs tags)
+ (use-file-dialog nil)
+ (pred
+ (lambda (ff)
+ (lexical-let* ((bk (bmkp-get-autofile-bookmark ff))
+ (btgs (and bk (bmkp-get-tags bk))))
+ (and btgs (bmkp-some (lambda (tag) (bmkp-has-tag-p bk tag)) tgs)))))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (icicle-must-pass-after-match-predicate pred)
+ (fil (or (and file (funcall pred file) file)
+ (read-file-name
+ "Find file: " nil nil t nil
+ (and (or (not (boundp 'icicle-mode))
+ (not icicle-mode))
+ pred))))
+ (bmk (bmkp-get-autofile-bookmark fil)))
+ (bookmark-jump bmk))))
+
+;;;###autoload (autoload 'bmkp-find-file-some-tags-other-window "bookmark+")
+(when (> emacs-major-version 21) ; Needs `read-file-name' with a PREDICATE arg.
+ (defun bmkp-find-file-some-tags-other-window (tags &optional file) ; `C-x 4 j t C-f +'
+ "`bmkp-find-file-some-tags', but in another window."
+ (interactive (list (bmkp-read-tags-completing nil nil current-prefix-arg)))
+ (lexical-let* ((tgs tags)
+ (use-file-dialog nil)
+ (pred
+ (lambda (ff)
+ (lexical-let* ((bk (bmkp-get-autofile-bookmark ff))
+ (btgs (and bk (bmkp-get-tags bk))))
+ (and btgs (bmkp-some (lambda (tag) (bmkp-has-tag-p bk tag)) tgs)))))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (icicle-must-pass-after-match-predicate pred)
+ (fil (or (and file (funcall pred file) file)
+ (read-file-name
+ "Find file: " nil nil t nil
+ (and (or (not (boundp 'icicle-mode))
+ (not icicle-mode))
+ pred))))
+ (bmk (bmkp-get-autofile-bookmark fil)))
+ (bookmark-jump-other-window bmk))))
+
+;;;###autoload (autoload 'bmkp-find-file-some-tags-regexp "bookmark+")
+(when (> emacs-major-version 21) ; Needs `read-file-name' with a PREDICATE arg.
+ (defun bmkp-find-file-some-tags-regexp (regexp &optional file) ; `C-x j t C-f % +'
+ "Visit a file or directory that has a tag matching REGEXP.
+You are prompted for the REGEXP."
+ (interactive (list (bmkp-read-regexp "Regexp for tags: ")))
+ (lexical-let* ((rg regexp)
+ (use-file-dialog nil)
+ (pred
+ (lambda (ff)
+ (let* ((bk (bmkp-get-autofile-bookmark ff))
+ (btgs (and bk (bmkp-get-tags bk))))
+ (and btgs (bmkp-some (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag)))
+ btgs)))))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (icicle-must-pass-after-match-predicate pred)
+ (fil (or (and file (funcall pred file) file)
+ (read-file-name
+ "Find file: " nil nil t nil
+ (and (or (not (boundp 'icicle-mode))
+ (not icicle-mode))
+ pred))))
+ (bmk (bmkp-get-autofile-bookmark fil)))
+ (bookmark-jump bmk))))
+
+;;;###autoload (autoload 'bmkp-find-file-some-tags-regexp-other-window "bookmark+")
+(when (> emacs-major-version 21) ; Needs `read-file-name' with a PREDICATE arg.
+ (defun bmkp-find-file-some-tags-regexp-other-window (regexp &optional file) ; `C-x 4 j t C-f % +'
+ "`bmkp-find-file-some-tags-regexp', but in another window."
+ (interactive (list (bmkp-read-regexp "Regexp for tags: ")))
+ (lexical-let* ((rg regexp)
+ (use-file-dialog nil)
+ (pred
+ (lambda (ff)
+ (let* ((bk (bmkp-get-autofile-bookmark ff))
+ (btgs (and bk (bmkp-get-tags bk))))
+ (and btgs (bmkp-some (lambda (tag) (bmkp-string-match-p rg (bmkp-tag-name tag)))
+ btgs)))))
+ (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
+ (icicle-must-pass-after-match-predicate pred)
+ (fil (or (and file (funcall pred file) file)
+ (read-file-name
+ "Find file: " nil nil t nil
+ (and (or (not (boundp 'icicle-mode))
+ (not icicle-mode))
+ pred))))
+ (bmk (bmkp-get-autofile-bookmark fil)))
+ (bookmark-jump-other-window bmk))))
+
+;;;###autoload (autoload 'bmkp-jump-in-navlist "bookmark+")
+(defun bmkp-jump-in-navlist (bookmark-name &optional flip-use-region-p) ; `C-x j N'
+ "Jump to a bookmark, choosing from those in the navigation list."
+ (interactive
+ (progn (unless bmkp-nav-alist
+ (bookmark-maybe-load-default-file)
+ (setq bmkp-nav-alist bookmark-alist)
+ (unless bmkp-nav-alist (error "No bookmarks"))
+ (setq bmkp-current-nav-bookmark (car bmkp-nav-alist))
+ (message "Bookmark navigation list is now the global bookmark list") (sit-for 2))
+ (let ((bookmark-alist bmkp-nav-alist))
+ (list (bookmark-completing-read "Jump to bookmark" (bmkp-default-bookmark-name))
+ current-prefix-arg))))
+ (bmkp-jump-1 bookmark-name 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-jump-in-navlist-other-window "bookmark+")
+(defun bmkp-jump-in-navlist-other-window (bookmark-name &optional flip-use-region-p) ; `C-x 4 j N'
+ "Same as `bmkp-jump-in-navlist', but use another window."
+ (interactive
+ (progn (unless bmkp-nav-alist
+ (bookmark-maybe-load-default-file)
+ (setq bmkp-nav-alist bookmark-alist)
+ (unless bmkp-nav-alist (error "No bookmarks"))
+ (setq bmkp-current-nav-bookmark (car bmkp-nav-alist))
+ (message "Bookmark navigation list is now the global bookmark list") (sit-for 2))
+ (let ((bookmark-alist bmkp-nav-alist))
+ (list (bookmark-completing-read "Jump to bookmark (in another window)"
+ (bmkp-default-bookmark-name))
+ current-prefix-arg))))
+ (bmkp-jump-1 bookmark-name 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-cycle "bookmark+")
+(defun bmkp-cycle (increment &optional other-window startoverp)
+ "Cycle through bookmarks in the navlist by INCREMENT (default: 1).
+Positive INCREMENT cycles forward. Negative INCREMENT cycles backward.
+Interactively, the prefix arg determines INCREMENT:
+ Plain `C-u': 1
+ otherwise: the numeric prefix arg value
+
+Plain `C-u' also means start over at first bookmark.
+
+You can set the navigation list using commands
+ `bmkp-choose-navlist-from-bookmark-list' and
+ `bmkp-choose-navlist-of-type'.
+
+You can cycle among bookmarks in the current buffer using
+ `bmkp-cycle-this-buffer' and
+ `bmkp-cycle-this-buffer-other-window.'
+
+In Lisp code:
+ Non-nil OTHER-WINDOW means jump to the bookmark in another window.
+ Non-nil STARTOVERP means reset `bmkp-current-nav-bookmark' to the
+ first bookmark in the navlist."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) nil startovr)))
+ (unless bmkp-nav-alist
+ (bookmark-maybe-load-default-file)
+ (when (and bookmark-alist (y-or-n-p "No navigation list. Use whole bookmark list? "))
+ (setq bmkp-nav-alist bookmark-alist)
+ (message "Navigation list is now the global bookmark list") (sit-for 2))
+ (unless bmkp-nav-alist (error "No bookmarks in navigation list"))
+ (setq bmkp-current-nav-bookmark (car bmkp-nav-alist)))
+ (unless (and bmkp-current-nav-bookmark (not startoverp)
+ (bmkp-get-bookmark bmkp-current-nav-bookmark 'NOERROR))
+ (setq bmkp-current-nav-bookmark (car bmkp-nav-alist)))
+ (if (bmkp-cycle-1 increment other-window startoverp)
+ (unless (or (bmkp-sequence-bookmark-p bmkp-current-nav-bookmark)
+ (bmkp-function-bookmark-p bmkp-current-nav-bookmark))
+ (message "Position: %9d, Bookmark: `%s'"
+ (point) (bmkp-bookmark-name-from-record bmkp-current-nav-bookmark)))
+ (message "Invalid bookmark: `%s'" (bmkp-bookmark-name-from-record bmkp-current-nav-bookmark))))
+
+;;;###autoload (autoload 'bmkp-cycle-other-window "bookmark+")
+(defun bmkp-cycle-other-window (increment &optional startoverp)
+ "Same as `bmkp-cycle' but uses another window."
+ (interactive "p")
+ (bmkp-cycle increment 'OTHER-WINDOW startoverp))
+
+;;;###autoload (autoload 'bmkp-cycle-this-file/buffer "bookmark+")
+(defun bmkp-cycle-this-file/buffer (increment &optional other-window startoverp)
+ "Cycle through bookmarks for this file/buffer by INCREMENT (default: 1).
+If visiting a file, this is `bmkp-cycle-this-file'.
+Otherwise, this is `bmkp-cycle-this-buffer'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) nil startovr)))
+ (if (buffer-file-name)
+ (bmkp-cycle-this-file increment other-window startoverp)
+ (bmkp-cycle-this-buffer increment other-window startoverp)))
+
+;;;###autoload (autoload 'bmkp-cycle-this-file/buffer-other-window "bookmark+")
+(defun bmkp-cycle-this-file/buffer-other-window (increment &optional startoverp)
+ "Same as `bmkp-cycle-this-file/buffer' but use other window."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-this-file/buffer increment 'OTHER-WINDOW startoverp))
+
+;;;###autoload (autoload 'bmkp-cycle-this-file "bookmark+")
+(defun bmkp-cycle-this-file (increment &optional other-window startoverp)
+ "Cycle through bookmarks for this file by INCREMENT (default: 1).
+Positive INCREMENT cycles forward. Negative INCREMENT cycles backward.
+Interactively, the prefix arg determines INCREMENT:
+ Plain `C-u': 1
+ otherwise: the numeric prefix arg value
+
+Plain `C-u' also means start over at first bookmark.
+
+You can cycle among bookmarks beyond the current file using
+`bmkp-cycle' and `bmkp-cycle-other-window.'
+
+You can set your preferred sort order for this-file bookmarks by
+customizing option `bmkp-this-file/buffer-cycle-sort-comparer'.
+
+To change the sort order without customizing, you can use \
+`\\[bmkp-this-file-bmenu-list]' to
+show the `*Bookmark List*' with only this file's bookmarks, sort
+them there, and use `\\[bmkp-choose-navlist-from-bookmark-list]', choosing \
+`CURRENT *Bookmark List*' as
+the navigation list.
+
+Then you can cycle the bookmarks using `bmkp-cycle'
+\(`\\[bmkp-next-bookmark-repeat]' etc.), instead of `bmkp-cycle-this-file'.
+
+In Lisp code:
+ Non-nil OTHER-WINDOW means jump to the bookmark in another window.
+ Non-nil STARTOVERP means reset `bmkp-current-nav-bookmark' to the
+ first bookmark in the navlist."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) nil startovr)))
+ (bookmark-maybe-load-default-file)
+ (let ((bmkp-sort-comparer bmkp-this-file/buffer-cycle-sort-comparer))
+ (setq bmkp-nav-alist (bmkp-sort-omit (bmkp-this-file-alist-only))))
+ (unless bmkp-nav-alist (error "No bookmarks for this file"))
+ (unless (and bmkp-current-nav-bookmark (not startoverp)
+ (bmkp-get-bookmark bmkp-current-nav-bookmark 'NOERROR)
+ (bmkp-this-file-p bmkp-current-nav-bookmark)) ; Exclude desktops etc.
+ (setq bmkp-current-nav-bookmark (car bmkp-nav-alist)))
+ (if (bmkp-cycle-1 increment other-window startoverp)
+ (unless (or (bmkp-sequence-bookmark-p bmkp-current-nav-bookmark)
+ (bmkp-function-bookmark-p bmkp-current-nav-bookmark))
+ (message "Position: %9d, Bookmark: `%s'"
+ (point) (bmkp-bookmark-name-from-record bmkp-current-nav-bookmark)))
+ (message "Invalid bookmark: `%s'" (bmkp-bookmark-name-from-record bmkp-current-nav-bookmark))))
+
+;;;###autoload (autoload 'bmkp-cycle-this-file-other-window "bookmark+")
+(defun bmkp-cycle-this-file-other-window (increment &optional startoverp)
+ "Same as `bmkp-cycle-this-file' but use other window."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-this-file increment 'OTHER-WINDOW startoverp))
+
+;;;###autoload (autoload 'bmkp-cycle-this-buffer "bookmark+")
+(defun bmkp-cycle-this-buffer (increment &optional other-window startoverp)
+ "Cycle through bookmarks in this buffer by INCREMENT (default: 1).
+Positive INCREMENT cycles forward. Negative INCREMENT cycles backward.
+Interactively, the prefix arg determines INCREMENT:
+ Plain `C-u': 1
+ otherwise: the numeric prefix arg value
+
+Plain `C-u' also means start over at first bookmark.
+
+You can cycle among bookmarks beyond the current buffer using
+`bmkp-cycle' and `bmkp-cycle-other-window.'
+
+You can set your preferred sort order for this-buffer bookmarks by
+customizing option `bmkp-this-file/buffer-cycle-sort-comparer'.
+
+To change the sort order without customizing, you can use \
+`\\[bmkp-this-buffer-bmenu-list]' to
+show the `*Bookmark List*' with only this buffer's bookmarks, sort
+them there, and use `\\[bmkp-choose-navlist-from-bookmark-list]', choosing \
+`CURRENT *Bookmark List*' as
+the navigation list.
+
+Then you can cycle the bookmarks using `bmkp-cycle'
+\(`\\[bmkp-next-bookmark-repeat]' etc.), instead of `bmkp-cycle-this-buffer'.
+
+In Lisp code:
+ Non-nil OTHER-WINDOW means jump to the bookmark in another window.
+ Non-nil STARTOVERP means reset `bmkp-current-nav-bookmark' to the
+ first bookmark in the navlist."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) nil startovr)))
+ (bookmark-maybe-load-default-file)
+ (let ((bmkp-sort-comparer bmkp-this-file/buffer-cycle-sort-comparer))
+ (setq bmkp-nav-alist (bmkp-sort-omit (bmkp-this-buffer-alist-only))))
+ (unless bmkp-nav-alist (error "No bookmarks in this buffer"))
+ (unless (and bmkp-current-nav-bookmark (not startoverp)
+ (bmkp-get-bookmark bmkp-current-nav-bookmark 'NOERROR)
+ (bmkp-this-buffer-p bmkp-current-nav-bookmark)) ; Exclude desktops etc.
+ (setq bmkp-current-nav-bookmark (car bmkp-nav-alist)))
+ (if (bmkp-cycle-1 increment other-window startoverp)
+ (unless (or (bmkp-sequence-bookmark-p bmkp-current-nav-bookmark)
+ (bmkp-function-bookmark-p bmkp-current-nav-bookmark))
+ (message "Position: %9d, Bookmark: `%s'"
+ (point) (bmkp-bookmark-name-from-record bmkp-current-nav-bookmark)))
+ (message "Invalid bookmark: `%s'" (bmkp-bookmark-name-from-record bmkp-current-nav-bookmark))))
+
+;;;###autoload (autoload 'bmkp-cycle-this-buffer-other-window "bookmark+")
+(defun bmkp-cycle-this-buffer-other-window (increment &optional startoverp)
+ "Same as `bmkp-cycle-this-buffer' but use other window."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-this-buffer increment 'OTHER-WINDOW startoverp))
+
+(defun bmkp-cycle-1 (increment &optional other-window startoverp)
+ "Helper for `bmkp-cycle*' commands.
+Do nothing if `bmkp-current-nav-bookmark' is an invalid bookmark.
+Return `bmkp-current-nav-bookmark', or nil if invalid.
+
+NOTE: If `pop-up-frames' is non-nil, then cycling inhibits automatic
+showing of annotations (`bookmark-automatically-show-annotations').
+This is to prevent change of frame focus, so cycling can continue
+properly.
+
+See `bmkp-cycle' for descriptions of the arguments."
+ (let ((bookmark-alist bmkp-nav-alist)
+ (bookmark (bmkp-get-bookmark bmkp-current-nav-bookmark 'NOERROR))
+ (bmkp-use-region (eq 'cycling-too bmkp-use-region)))
+ (unless bookmark-alist (error "No bookmarks for cycling"))
+ (when bookmark ; Skip bookmarks with bad names.
+ (setq bmkp-current-nav-bookmark
+ (if startoverp
+ (car bookmark-alist)
+ (let ((index (bmkp-list-position bookmark bookmark-alist #'eq)))
+ (if index
+ (nth (mod (+ increment index) (length bookmark-alist)) bookmark-alist)
+ (message "bmkp-cycle-1: Bookmark `%s' is not in navlist"
+ (bmkp-bookmark-name-from-record bmkp-current-nav-bookmark))
+ (car bookmark-alist)))))
+ (let ((bookmark-automatically-show-annotations ; Prevent possible frame focus change.
+ (and bookmark-automatically-show-annotations (not pop-up-frames))))
+ (if other-window
+ (bookmark-jump-other-window (bmkp-bookmark-name-from-record bmkp-current-nav-bookmark))
+ (save-selected-window (bmkp-bookmark-name-from-record (bookmark-jump bmkp-current-nav-bookmark))))))
+ (and bookmark bmkp-current-nav-bookmark))) ; Return nil if not a valid bookmark.
+
+;; Same as `icicle-list-position' in `icicles-fn.el'.
+;; Simple version of `cl-position' for all Emacs versions.
+(defun bmkp-list-position (item items &optional test)
+ "Find the first occurrence of ITEM in list ITEMS.
+Return the index of the matching item, or nil if not found.
+Items are compared using binary predicate TEST, or `equal' if TEST is
+nil."
+ (unless test (setq test 'equal))
+ (let ((pos 0))
+ (catch 'bmkp-list-position
+ (dolist (itm items)
+ (when (funcall test item itm) (throw 'bmkp-list-position pos))
+ (setq pos (1+ pos)))
+ nil)))
+
+;;;###autoload (autoload 'bmkp-next-bookmark "bookmark+")
+(defun bmkp-next-bookmark (n &optional startoverp) ; You can bind this to a repeatable key
+ "Jump to the Nth next bookmark in the bookmark navigation list.
+N defaults to 1, meaning the next bookmark.
+Plain `C-u' means start over at first bookmark.
+See also `bmkp-cycle'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle n nil startoverp))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark "bookmark+")
+(defun bmkp-previous-bookmark (n &optional startoverp) ; You can bind this to a repeatable key
+ "Jump to the Nth previous bookmark in the bookmark navigation list.
+See `bmkp-next-bookmark'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle (- n) nil startoverp))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-other-window "bookmark+")
+(defun bmkp-next-bookmark-other-window (n &optional startoverp) ; You can bind this to a repeatable key
+ "Jump to Nth next bookmark in bookmark navlist in another window.
+N defaults to 1, meaning the next bookmark.
+Plain `C-u' means start over at first bookmark.
+See also `bmkp-cycle'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle n 'OTHER-WINDOW startoverp))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-other-window "bookmark+")
+(defun bmkp-previous-bookmark-other-window (n &optional startoverp) ; You can bind this to a repeatable key
+ "Jump to Nth previous bookmark in bookmark navlist in another window.
+See `bmkp-next-bookmark'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle (- n) 'OTHER-WINDOW startoverp))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-repeat "bookmark+")
+(defun bmkp-next-bookmark-repeat (arg) ; `C-x x right', `C-x x f', `C-x x C-f'
+ "Jump to the Nth-next bookmark in the bookmark navigation list.
+This is a repeatable version of `bmkp-next-bookmark'.
+N defaults to 1, meaning the next bookmark.
+Plain `C-u' means start over at the first bookmark (and no repeat)."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-next-bookmark))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-repeat "bookmark+")
+(defun bmkp-previous-bookmark-repeat (arg) ; `C-x x left', `C-x x b', `C-x x C-b'
+ "Jump to the Nth-previous bookmark in the bookmark navigation list.
+See `bmkp-next-bookmark-repeat'."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-previous-bookmark))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-other-window-repeat "bookmark+")
+(defun bmkp-next-bookmark-other-window-repeat (arg) ; `C-x x right', `C-x x f', `C-x x C-f'
+ "Jump to Nth-next bookmark in bookmark navlist in another window.
+This is a repeatable version of `bmkp-next-bookmark'.
+N defaults to 1, meaning the next bookmark.
+Plain `C-u' means start over at the first bookmark (and no repeat)."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-next-bookmark-other-window))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-other-window-repeat "bookmark+")
+(defun bmkp-previous-bookmark-other-window-repeat (arg) ; `C-x x left', `C-x x b', `C-x x C-b'
+ "Jump to Nth-previous bookmark in bookmark navlist in another window.
+See `bmkp-next-bookmark-repeat'."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-previous-bookmark-other-window))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-this-file/buffer "bookmark+")
+(defun bmkp-next-bookmark-this-file/buffer (n &optional startoverp) ; Bind to repeatable key, e.g. `S-f2'
+ "Jump to the Nth-next bookmark for the current file/buffer.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one.
+See also `bmkp-cycle-this-file/buffer'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-this-file/buffer n nil startoverp))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-this-file/buffer "bookmark+")
+(defun bmkp-previous-bookmark-this-file/buffer (n &optional startoverp) ; Bind to repeatable key, e.g. `f2'
+ "Jump to the Nth-previous bookmark for the current file/buffer.
+See `bmkp-next-bookmark-this-file/buffer'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-this-file/buffer (- n) nil startoverp))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-this-file/buffer-repeat "bookmark+")
+(defun bmkp-next-bookmark-this-file/buffer-repeat (arg)
+ ; `C-x x down', `C-x x n', `C-x x C-n', `C-x x mouse-wheel-up'
+ "Jump to the Nth next bookmark for the current file/buffer.
+This is a repeatable version of `bmkp-next-bookmark-this-file/buffer'.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one (and no repeat)."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-next-bookmark-this-file/buffer))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-this-file/buffer-repeat "bookmark+")
+(defun bmkp-previous-bookmark-this-file/buffer-repeat (arg)
+ ; `C-x x up', `C-x x p', `C-x x C-p', `C-x x mouse-wheel-down'
+ "Jump to the Nth previous bookmark for the current file/buffer.
+See `bmkp-next-bookmark-this-file/buffer-repeat'."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-previous-bookmark-this-file/buffer))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-this-file "bookmark+")
+(defun bmkp-next-bookmark-this-file (n &optional startoverp) ; Bind to repeatable key, e.g. `S-f2'
+ "Jump to the Nth-next bookmark for the current file.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one.
+See also `bmkp-cycle-this-file'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-this-file n nil startoverp))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-this-file "bookmark+")
+(defun bmkp-previous-bookmark-this-file (n &optional startoverp) ; Bind to repeatable key, e.g. `f2'
+ "Jump to the Nth-previous bookmark for the current file.
+See `bmkp-next-bookmark-this-file'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-this-file (- n) nil startoverp))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-this-file-repeat "bookmark+")
+(defun bmkp-next-bookmark-this-file-repeat (arg)
+ "Jump to the Nth next bookmark for the current file.
+This is a repeatable version of `bmkp-next-bookmark-this-file'.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one (and no repeat)."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-next-bookmark-this-file))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-this-file-repeat "bookmark+")
+(defun bmkp-previous-bookmark-this-file-repeat (arg)
+ "Jump to the Nth previous bookmark for the current file.
+See `bmkp-next-bookmark-this-file-repeat'."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-previous-bookmark-this-file))
+
+
+;;;###autoload (autoload 'bmkp-next-bookmark-this-buffer "bookmark+")
+(defun bmkp-next-bookmark-this-buffer (n &optional startoverp) ; Bind to repeatable key, e.g. `S-f2'
+ "Jump to the Nth-next bookmark in the current buffer.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one.
+See also `bmkp-cycle-this-buffer'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-this-buffer n nil startoverp))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-this-buffer "bookmark+")
+(defun bmkp-previous-bookmark-this-buffer (n &optional startoverp) ; Bind to repeatable key, e.g. `f2'
+ "Jump to the Nth-previous bookmark in the current buffer.
+See `bmkp-next-bookmark-this-buffer'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-this-buffer (- n) nil startoverp))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-this-buffer-repeat "bookmark+")
+(defun bmkp-next-bookmark-this-buffer-repeat (arg)
+ "Jump to the Nth next bookmark in the current buffer.
+This is a repeatable version of `bmkp-next-bookmark-this-buffer'.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one (and no repeat)."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-next-bookmark-this-buffer))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-this-buffer-repeat "bookmark+")
+(defun bmkp-previous-bookmark-this-buffer-repeat (arg)
+ "Jump to the Nth previous bookmark in the current buffer.
+See `bmkp-next-bookmark-this-buffer-repeat'."
+ (interactive "P")
+ (bmkp-repeat-command 'bmkp-previous-bookmark-this-buffer))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-w32 "bookmark+")
+(defun bmkp-next-bookmark-w32 (n &optional startoverp) ; You can bind this to a repeatable key
+ "Windows `Open' the Nth next bookmark in the bookmark navigation list.
+MS Windows only. Invokes the program associated with the file type.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one.
+See also `bmkp-cycle'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (let ((bmkp-use-w32-browser-p t)) (bmkp-cycle n nil startoverp)))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-w32 "bookmark+")
+(defun bmkp-previous-bookmark-w32 (n &optional startoverp) ; You can bind this to a repeatable key
+ "Windows `Open' the Nth previous bookmark in the bookmark navlist.
+See `bmkp-next-bookmark-w32'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (let ((bmkp-use-w32-browser-p t)) (bmkp-cycle (- n) nil startoverp)))
+
+;;;###autoload (autoload 'bmkp-next-bookmark-w32-repeat "bookmark+")
+(defun bmkp-next-bookmark-w32-repeat (arg) ; `C-x x next'
+ "Windows `Open' the Nth next bookmark in the bookmark navigation list.
+This is a repeatable version of `bmkp-next-bookmark'.
+N defaults to 1, meaning the next bookmark.
+Plain `C-u' means start over at the first one (and no repeat)."
+ (interactive "P")
+ (let ((bmkp-use-w32-browser-p t)) (bmkp-repeat-command 'bmkp-next-bookmark)))
+
+;;;###autoload (autoload 'bmkp-previous-bookmark-w32-repeat "bookmark+")
+(defun bmkp-previous-bookmark-w32-repeat (arg) ; `C-x x prior'
+ "Windows `Open' the Nth previous bookmark in the bookmark navlist.
+See `bmkp-next-bookmark-w32-repeat'."
+ (interactive "P")
+ (let ((bmkp-use-w32-browser-p t)) (bmkp-repeat-command 'bmkp-previous-bookmark)))
+
+;; In spite of their names, `bmkp-cycle-specific-(buffers|files)*' just cycle bookmarks in the
+;; current buffer or file. There is no way to choose multiple buffers or files.
+;;
+;; `bmkp-cycle-autonamed', `bmkp-cycle-autonamed-other-window',
+;; `bmkp-cycle-bookmark-list', `bmkp-cycle-bookmark-list-other-window',
+;; `bmkp-cycle-desktop',
+;; `bmkp-cycle-dired', `bmkp-cycle-dired-other-window',
+;; `bmkp-cycle-eww', `bmkp-cycle-eww-other-window',
+;; `bmkp-cycle-file', `bmkp-cycle-file-other-window',
+;; `bmkp-cycle-gnus', `bmkp-cycle-gnus-other-window',
+;; `bmkp-cycle-info', `bmkp-cycle-info-other-window',
+;; `bmkp-cycle-lighted', `bmkp-cycle-lighted-other-window',
+;; `bmkp-cycle-local-file', `bmkp-cycle-local-file-other-window',
+;; `bmkp-cycle-man', `bmkp-cycle-man-other-window',
+;; `bmkp-cycle-non-file', `bmkp-cycle-non-file-other-window',
+;; `bmkp-cycle-remote-file', `bmkp-cycle-remote-file-other-window',
+;; `bmkp-cycle-specific-buffers', `bmkp-cycle-specific-buffers-other-window',
+;; `bmkp-cycle-specific-files', `bmkp-cycle-specific-files-other-window',
+;; `bmkp-cycle-variable-list',
+;; `bmkp-cycle-url', `bmkp-cycle-url-other-window',
+;;
+(bmkp-define-cycle-command "autonamed")
+(bmkp-define-cycle-command "autonamed" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "bookmark-list") ; No other-window version needed
+(bmkp-define-cycle-command "desktop") ; No other-window version needed
+(bmkp-define-cycle-command "dired")
+(bmkp-define-cycle-command "dired" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "eww")
+(bmkp-define-cycle-command "eww" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "file")
+(bmkp-define-cycle-command "file" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "gnus")
+(bmkp-define-cycle-command "gnus" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "info")
+(bmkp-define-cycle-command "info" 'OTHER-WINDOW)
+(when (featurep 'bookmark+-lit)
+ (bmkp-define-cycle-command "lighted")
+ (bmkp-define-cycle-command "lighted" 'OTHER-WINDOW))
+(bmkp-define-cycle-command "local-file")
+(bmkp-define-cycle-command "local-file" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "man")
+(bmkp-define-cycle-command "man" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "non-file")
+(bmkp-define-cycle-command "non-file" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "remote-file")
+(bmkp-define-cycle-command "remote-file" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "specific-buffers")
+(bmkp-define-cycle-command "specific-buffers" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "specific-files")
+(bmkp-define-cycle-command "specific-files" 'OTHER-WINDOW)
+(bmkp-define-cycle-command "variable-list") ; No other-window version needed
+(bmkp-define-cycle-command "url")
+(bmkp-define-cycle-command "url" 'OTHER-WINDOW)
+
+;; `bmkp-next-autonamed-bookmark', `bmkp-next-autonamed-bookmark-other-window',
+;; `bmkp-next-autonamed-bookmark-repeat', `bmkp-next-autonamed-bookmark-other-window-repeat',
+;; `bmkp-next-bookmark-list-bookmark',
+;; `bmkp-next-bookmark-list-bookmark-repeat',
+;; `bmkp-next-bookmark-list-bookmark-other-window',
+;; `bmkp-next-bookmark-list-bookmark-other-window-repeat',
+;; `bmkp-next-desktop-bookmark',
+;; `bmkp-next-desktop-bookmark-repeat',
+;; `bmkp-next-desktop-bookmark-other-window',
+;; `bmkp-next-desktop-bookmark-other-window-repeat',
+;; `bmkp-next-dired-bookmark',
+;; `bmkp-next-dired-bookmark-repeat',
+;; `bmkp-next-dired-bookmark-other-window',
+;; `bmkp-next-dired-bookmark-other-window-repeat',
+;; `bmkp-next-eww-bookmark',
+;; `bmkp-next-eww-bookmark-repeat',
+;; `bmkp-next-eww-bookmark-other-window',
+;; `bmkp-next-eww-bookmark-other-window-repeat',
+;; `bmkp-next-file-bookmark',
+;; `bmkp-next-file-bookmark-repeat',
+;; `bmkp-next-file-bookmark-other-window',
+;; `bmkp-next-file-bookmark-other-window-repeat',
+;; `bmkp-next-gnus-bookmark',
+;; `bmkp-next-gnus-bookmark-repeat',
+;; `bmkp-next-gnus-bookmark-other-window',
+;; `bmkp-next-gnus-bookmark-other-window-repeat',
+;; `bmkp-next-info-bookmark',
+;; `bmkp-next-info-bookmark-repeat',
+;; `bmkp-next-info-bookmark-other-window',
+;; `bmkp-next-info-bookmark-other-window-repeat',
+;; `bmkp-next-lighted-bookmark',
+;; `bmkp-next-lighted-bookmark-repeat',
+;; `bmkp-next-lighted-bookmark-other-window',
+;; `bmkp-next-lighted-bookmark-other-window-repeat',
+;; `bmkp-next-local-file-bookmark',
+;; `bmkp-next-local-file-bookmark-repeat',
+;; `bmkp-next-local-file-bookmark-other-window',
+;; `bmkp-next-local-file-bookmark-other-window-repeat',
+;; `bmkp-next-man-bookmark',
+;; `bmkp-next-man-bookmark-repeat',
+;; `bmkp-next-man-bookmark-other-window',
+;; `bmkp-next-man-bookmark-other-window-repeat',
+;; `bmkp-next-non-file-bookmark',
+;; `bmkp-next-non-file-bookmark-repeat',
+;; `bmkp-next-non-file-bookmark-other-window',
+;; `bmkp-next-non-file-bookmark-other-window-repeat',
+;; `bmkp-next-remote-file-bookmark',
+;; `bmkp-next-remote-file-bookmark-repeat',
+;; `bmkp-next-remote-file-bookmark-other-window',
+;; `bmkp-next-remote-file-bookmark-other-window-repeat',
+;; `bmkp-next-specific-buffers-bookmark',
+;; `bmkp-next-specific-buffers-bookmark-repeat',
+;; `bmkp-next-specific-buffers-bookmark-other-window',
+;; `bmkp-next-specific-buffers-bookmark-other-window-repeat',
+;; `bmkp-next-specific-files-bookmark',
+;; `bmkp-next-specific-files-bookmark-repeat',
+;; `bmkp-next-specific-files-bookmark-other-window',
+;; `bmkp-next-specific-files-bookmark-other-window-repeat',
+;; `bmkp-next-variable-list-bookmark',
+;; `bmkp-next-variable-list-bookmark-repeat',
+;; `bmkp-next-variable-list-bookmark-other-window',
+;; `bmkp-next-variable-list-bookmark-other-window-repeat',
+;; `bmkp-next-url-bookmark',
+;; `bmkp-next-url-bookmark-repeat'.
+;; `bmkp-next-url-bookmark-other-window',
+;; `bmkp-next-url-bookmark-other-window-repeat'.
+;;
+;; `bmkp-previous-autonamed-bookmark',
+;; `bmkp-previous-autonamed-bookmark-repeat',
+;; `bmkp-previous-autonamed-bookmark-other-window',
+;; `bmkp-previous-autonamed-bookmark-other-window-repeat',
+;; `bmkp-previous-bookmark-list-bookmark',
+;; `bmkp-previous-bookmark-list-bookmark-repeat',
+;; `bmkp-previous-bookmark-list-bookmark-other-window',
+;; `bmkp-previous-bookmark-list-bookmark-other-window-repeat',
+;; `bmkp-previous-desktop-bookmark',
+;; `bmkp-previous-desktop-bookmark-repeat',
+;; `bmkp-previous-desktop-bookmark-other-window',
+;; `bmkp-previous-desktop-bookmark--other-windowrepeat',
+;; `bmkp-previous-dired-bookmark',
+;; `bmkp-previous-dired-bookmark-repeat',
+;; `bmkp-previous-dired-bookmark-other-window',
+;; `bmkp-previous-dired-bookmark-other-window-repeat',
+;; `bmkp-previous-eww-bookmark',
+;; `bmkp-previous-eww-bookmark-repeat',
+;; `bmkp-previous-eww-bookmark-other-window',
+;; `bmkp-previous-eww-bookmark-other-window-repeat',
+;; `bmkp-previous-file-bookmark',
+;; `bmkp-previous-file-bookmark-repeat',
+;; `bmkp-previous-file-bookmark-other-window',
+;; `bmkp-previous-file-bookmark-other-window-repeat',
+;; `bmkp-previous-gnus-bookmark',
+;; `bmkp-previous-gnus-bookmark-repeat',
+;; `bmkp-previous-gnus-bookmark-other-window',
+;; `bmkp-previous-gnus-bookmark-other-window-repeat',
+;; `bmkp-previous-info-bookmark',
+;; `bmkp-previous-info-bookmark-repeat',
+;; `bmkp-previous-info-bookmark-other-window',
+;; `bmkp-previous-info-bookmark-other-window-repeat',
+;; `bmkp-previous-lighted-bookmark',
+;; `bmkp-previous-lighted-bookmark-repeat',
+;; `bmkp-previous-lighted-bookmark-other-window',
+;; `bmkp-previous-lighted-bookmark-other-window-repeat',
+;; `bmkp-previous-local-file-bookmark',
+;; `bmkp-previous-local-file-bookmark-repeat',
+;; `bmkp-previous-local-file-bookmark-other-window',
+;; `bmkp-previous-local-file-bookmark-other-window-repeat',
+;; `bmkp-previous-man-bookmark',
+;; `bmkp-previous-man-bookmark-repeat',
+;; `bmkp-previous-man-bookmark-other-window',
+;; `bmkp-previous-man-bookmark-other-window-repeat',
+;; `bmkp-previous-non-file-bookmark',
+;; `bmkp-previous-non-file-bookmark-repeat',
+;; `bmkp-previous-non-file-bookmark-other-window',
+;; `bmkp-previous-non-file-bookmark-other-window-repeat',
+;; `bmkp-previous-remote-file-bookmark',
+;; `bmkp-previous-remote-file-bookmark-repeat',
+;; `bmkp-previous-remote-file-bookmark-other-window',
+;; `bmkp-previous-remote-file-bookmark--other-windowrepeat',
+;; `bmkp-previous-specific-buffers-bookmark',
+;; `bmkp-previous-specific-buffers-bookmark-repeat',
+;; `bmkp-previous-specific-buffers-bookmark-other-window',
+;; `bmkp-previous-specific-buffers-bookmark-other-window-repeat',
+;; `bmkp-previous-specific-files-bookmark',
+;; `bmkp-previous-specific-files-bookmark-repeat',
+;; `bmkp-previous-specific-files-bookmark-other-window',
+;; `bmkp-previous-specific-files-bookmark-other-window-repeat',
+;; `bmkp-previous-variable-list-bookmark',
+;; `bmkp-previous-variable-list-bookmark-repeat',
+;; `bmkp-previous-variable-list-bookmark-other-window',
+;; `bmkp-previous-variable-list-bookmark-other-window-repeat',
+;; `bmkp-previous-url-bookmark',
+;; `bmkp-previous-url-bookmark-repeat'.
+;; `bmkp-previous-url-bookmark-other-window',
+;; `bmkp-previous-url-bookmark-other-window-repeat'.
+;;
+(bmkp-define-next+prev-cycle-commands "autonamed")
+(bmkp-define-next+prev-cycle-commands "autonamed" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "bookmark-list")
+(bmkp-define-next+prev-cycle-commands "desktop")
+(bmkp-define-next+prev-cycle-commands "dired")
+(bmkp-define-next+prev-cycle-commands "dired" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "eww")
+(bmkp-define-next+prev-cycle-commands "eww" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "file")
+(bmkp-define-next+prev-cycle-commands "file" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "gnus")
+(bmkp-define-next+prev-cycle-commands "gnus" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "info")
+(bmkp-define-next+prev-cycle-commands "info" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "lighted")
+(bmkp-define-next+prev-cycle-commands "lighted" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "local-file")
+(bmkp-define-next+prev-cycle-commands "local-file" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "man")
+(bmkp-define-next+prev-cycle-commands "man" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "non-file")
+(bmkp-define-next+prev-cycle-commands "non-file" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "remote-file")
+(bmkp-define-next+prev-cycle-commands "remote-file" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "specific-buffers")
+(bmkp-define-next+prev-cycle-commands "specific-buffers" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "specific-files")
+(bmkp-define-next+prev-cycle-commands "specific-files" 'OTHER-WINDOW)
+(bmkp-define-next+prev-cycle-commands "variable-list")
+(bmkp-define-next+prev-cycle-commands "url")
+(bmkp-define-next+prev-cycle-commands "url" 'OTHER-WINDOW)
+
+;;;###autoload (autoload 'bmkp-toggle-autonamed-bookmark-set/delete "bookmark+")
+(defun bmkp-toggle-autonamed-bookmark-set/delete (&optional position allp)
+ ; Bound globally to `C-x x RET', `C-x x c RET'
+ "If there is an autonamed bookmark at point, delete it, else create one.
+The bookmark created has no region. Its name is formatted according
+to option `bmkp-autoname-bookmark-function'.
+
+With a prefix arg, delete *ALL* autonamed bookmarks for this buffer.
+
+Non-interactively, act at POSITION, not point. If nil, act at point."
+ (interactive "d\nP")
+ (unless position (setq position (point)))
+ (if allp
+ (bmkp-delete-all-autonamed-for-this-buffer)
+ (let ((bmk-name (funcall bmkp-autoname-bookmark-function position)))
+ (if (not (bmkp-get-bookmark-in-alist bmk-name 'NOERROR))
+ (let ((mark-active nil)) ; Do not set a region bookmark.
+ (bookmark-set bmk-name)
+ (message "Set bookmark `%s'" bmk-name))
+ (bookmark-delete bmk-name)
+ (message "Deleted bookmark `%s'" bmk-name)))))
+
+;;;###autoload (autoload 'bmkp-set-autonamed-bookmark "bookmark+")
+(defun bmkp-set-autonamed-bookmark (&optional position msg-p)
+ "Set an autonamed bookmark at point.
+The bookmark created has no region. Its name is formatted according
+to option `bmkp-autoname-bookmark-function'.
+Non-interactively:
+ - Act at POSITION, not point. If nil, act at point.
+ - Non-nil optional arg MSG-P means display a status message."
+ (interactive (list (point) 'MSG))
+ (unless position (setq position (point)))
+ (let ((bmk-name (funcall bmkp-autoname-bookmark-function position))
+ (mark-active nil)) ; Do not set a region bookmark.
+ (bookmark-set bmk-name)
+ (when msg-p (message "Set bookmark `%s'" bmk-name))))
+
+;;;###autoload (autoload 'bmkp-set-autonamed-bookmark-at-line "bookmark+")
+(defun bmkp-set-autonamed-bookmark-at-line (&optional number)
+ "Set an autonamed bookmark at the beginning of the current line.
+With a prefix arg, set it at the line whose number is the numeric
+prefix value."
+ (interactive (list (and current-prefix-arg (prefix-numeric-value current-prefix-arg))))
+ (if (not number)
+ (bmkp-set-autonamed-bookmark (line-beginning-position))
+ (save-excursion
+ (goto-char (point-min))
+ (let ((inhibit-field-text-motion t))
+ (bmkp-set-autonamed-bookmark (line-beginning-position number))))))
+
+(when (> emacs-major-version 21)
+ (defun bmkp-occur-create-autonamed-bookmarks (&optional msg-p) ; Bound to `C-c C-M-B' (aka `C-c C-M-S-b')
+ "Create an autonamed bookmark for each `occur' hit.
+You can use this only in `Occur' mode (commands such as `occur' and
+`multi-occur').
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive "p")
+ (unless (eq major-mode 'occur-mode) (error "You must be in `occur-mode'"))
+ (let ((count 0))
+ (save-excursion
+ (goto-char (point-min))
+ (while (condition-case nil (progn (occur-next) t) (error nil))
+ (let* ((pos (get-text-property (point) 'occur-target))
+ (buf (and pos (marker-buffer pos))))
+ (when buf
+ (with-current-buffer buf
+ (goto-char pos)
+ (bmkp-set-autonamed-bookmark (point)))
+ (setq count (1+ count))))))
+ (when msg-p (message "Created %d autonamed bookmarks" count)))))
+
+;;;###autoload (autoload 'bmkp-set-autonamed-regexp-buffer "bookmark+")
+(defun bmkp-set-autonamed-regexp-buffer (regexp &optional msg-p)
+ "Set autonamed bookmarks at matches for REGEXP in the buffer.
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive (list (bmkp-read-regexp) 'MSG))
+ (bmkp-set-autonamed-regexp-region regexp (point-min) (point-max) msg-p))
+
+;;;###autoload (autoload 'bmkp-set-autonamed-regexp-region "bookmark+")
+(defun bmkp-set-autonamed-regexp-region (regexp beg end &optional msg-p)
+ "Set autonamed bookmarks at matches for REGEXP in the region.
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive (list (bmkp-read-regexp) (region-beginning) (region-end) 'MSG))
+ (let ((count 0))
+ (save-excursion
+ (goto-char beg)
+ (while (re-search-forward regexp end t)
+ (bmkp-set-autonamed-bookmark (point))
+ (setq count (1+ count))
+ (forward-line 1)))
+ (when msg-p (message "Set %d autonamed bookmarks" count))))
+
+(defun bmkp-autoname-bookmark-function-default (position)
+ "Return a bookmark name using POSITION and the current buffer name.
+The name is composed as follows:
+ POSITION followed by a space and then the buffer name.
+ The position value is prefixed with zeros to comprise 9 characters.
+ For example, for POSITION value 31416 and current buffer `my-buffer',
+ the name returned would be `000031416 my-buffer'"
+ (format "%09d %s" (abs position) (buffer-name)))
+
+;;;###autoload (autoload 'bmkp-delete-all-autonamed-for-this-buffer "bookmark+")
+(defun bmkp-delete-all-autonamed-for-this-buffer (&optional msg-p)
+ "Delete all autonamed bookmarks for the current buffer.
+Interactively, or with non-nil arg MSG-P, require confirmation.
+To be deleted, a bookmark name must be an autonamed bookmark whose
+buffer part names the current buffer."
+ (interactive "p")
+ (let ((bmks-to-delete (mapcar #'bmkp-bookmark-name-from-record
+ (bmkp-autonamed-this-buffer-alist-only))))
+ (if (null bmks-to-delete)
+ (when msg-p (message "No autonamed bookmarks for buffer `%s'" (buffer-name)))
+ (when (or (not msg-p)
+ (y-or-n-p (format "Delete ALL autonamed bookmarks for buffer `%s'? " (buffer-name))))
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bmk bmks-to-delete) (bookmark-delete bmk 'BATCHP))) ; No refresh yet.
+ (bmkp-refresh/rebuild-menu-list nil (not msg-p)) ; Now refresh, after iterate.
+ (when msg-p (message "Deleted all bookmarks for buffer `%s'" (buffer-name)))))))
+
+;; You can use this in `kill-buffer-hook'.
+(defun bmkp-delete-autonamed-this-buffer-no-confirm (&optional no-refresh-p)
+ "Delete all autonamed bookmarks for this buffer, without confirmation.
+Non-nil optional arg NO-REFRESH-P means do not refresh/rebuild the
+bookmark-list."
+ (when (and bookmarks-already-loaded bookmark-alist)
+ (let ((bmks-to-delete (mapcar #'bmkp-bookmark-name-from-record
+ (bmkp-autonamed-this-buffer-alist-only)))
+ (bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bmk bmks-to-delete) (bookmark-delete bmk 'BATCHP))) ; No refresh yet.
+ (unless no-refresh-p
+ (bmkp-refresh/rebuild-menu-list nil 'BATCHP)))) ; Now refresh, after iterate.
+
+
+;; You can use this in `kill-emacs-hook'.
+(defun bmkp-delete-autonamed-no-confirm ()
+ "Delete all autonamed bookmarks for all buffers, without confirmation."
+ (when (and bookmarks-already-loaded bookmark-alist)
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (buf (buffer-list))
+ (with-current-buffer buf
+ (bmkp-delete-autonamed-this-buffer-no-confirm 'NO-REFRESH-P)))) ; No refresh yet.
+ (bmkp-refresh/rebuild-menu-list nil 'BATCHP))) ; Now refresh, after iterate.
+
+(cond ((fboundp 'define-minor-mode)
+ ;; Emacs 21 and later. Eval this so that even if the library is byte-compiled with Emacs 20,
+ ;; loading it into Emacs 21+ will define variable `bmkp-automatic-bookmark-mode'.
+ (eval '(define-minor-mode bmkp-automatic-bookmark-mode
+ "Toggle automatic setting of a bookmark when Emacs is idle.
+Non-interactively, turn automatic bookmarking on for the current
+buffer if and only if ARG is positive.
+
+To enable or disable automatic bookmarking in all buffers, use
+`bmkp-global-automatic-bookmark-mode'.
+
+When the mode is enabled in the current buffer, a bookmark is
+automatically set every `bmkp-automatic-bookmark-mode-delay' seconds,
+using the setting function that is the value of option
+`bmkp-automatic-bookmark-set-function'. Note that a buffer must be
+current (selected) for an automatic bookmark to be created there - it
+is not enough that the mode be enabled in the buffer.
+
+Turning the mode on and off runs hooks
+`bmkp-automatic-bookmark-mode-on-hook' and
+`bmkp-automatic-bookmark-mode-off-hook', respectively.
+
+If you want the automatic bookmarks to be temporary (not saved to your
+bookmark file), then customize option
+`bmkp-autotemp-bookmark-predicates' so that it includes the kind of
+bookmarks that are set by `bmkp-automatic-bookmark-set-function'.
+For example, if automatic bookmarking sets autonamed bookmarks, then
+`bmkp-autotemp-bookmark-predicates' should include
+`bmkp-autonamed-bookmark-p' or
+`bmkp-autonamed-this-buffer-bookmark-p'.
+
+If you want the automatically created bookmarks to be highlighted,
+then customize option `bmkp-auto-light-when-set' to highlight
+bookmarks of the appropriate kind. For example, to highlight
+autonamed bookmarks set it to `autonamed-bookmark'.
+
+NOTE: If you use Emacs 21 then there is no global version of the mode
+- that is, there is no command `bmkp-global-automatic-bookmark-mode'."
+ :init-value nil :group 'bookmark-plus :require 'bookmark+
+ :lighter bmkp-automatic-bookmark-mode-lighter
+ :link `(url-link :tag "Send Bug Report"
+ ,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
+Bookmark bug: \
+&body=Describe bug here, starting with `emacs -Q'. \
+Don't forget to mention your Emacs and library versions."))
+ :link '(url-link :tag "Download" "https://www.emacswiki.org/emacs/download/bookmark%2b.el")
+ :link '(url-link :tag "Description" "https://www.emacswiki.org/emacs/BookmarkPlus")
+ :link '(emacs-commentary-link :tag "Commentary" "bookmark+")
+ (when bmkp-automatic-bookmark-mode-timer
+ (cancel-timer bmkp-automatic-bookmark-mode-timer)
+ (setq bmkp-automatic-bookmark-mode-timer nil))
+ (when bmkp-automatic-bookmark-mode
+ (setq bmkp-automatic-bookmark-mode-timer
+ (run-with-idle-timer bmkp-automatic-bookmark-mode-delay 'REPEAT
+ (lambda ()
+ (when bmkp-automatic-bookmark-mode
+ (bmkp-set-automatic-bookmark))))))
+ (when (interactive-p)
+ (message "Automatic bookmarking is now %s in buffer `%s'"
+ (if bmkp-automatic-bookmark-mode "ON" "OFF") (buffer-name)))))
+
+ (eval '(defun bmkp-turn-on-automatic-bookmark-mode ()
+ "Turn on `bmkp-automatic-bookmark-mode'."
+ (bmkp-automatic-bookmark-mode 1)))
+
+ (when (fboundp 'define-globalized-minor-mode) ; Emacs 22+, not 21.
+ (eval '(define-globalized-minor-mode bmkp-global-automatic-bookmark-mode
+ bmkp-automatic-bookmark-mode
+ bmkp-turn-on-automatic-bookmark-mode
+ :group 'bookmark-plus :require 'bookmark+))))
+ (t ; Emacs 20.
+ (defun bmkp-automatic-bookmark-mode (&optional arg)
+ "Toggle automatic setting of a bookmark when Emacs is idle.
+Non-interactively, turn automatic bookmarking on if and only if ARG is
+positive.
+
+When the mode is enabled, a bookmark is automatically set every
+`bmkp-automatic-bookmark-mode-delay' seconds, using the setting
+function that is the value of option
+`bmkp-automatic-bookmark-set-function'. Note that a buffer must be
+current (selected) for an automatic bookmark to be created there - it
+is not enough that the mode be enabled in the buffer.
+
+If you want these bookmarks to be temporary (not saved to your
+bookmark file), then customize option
+`bmkp-autotemp-bookmark-predicates' so that it includes the kind of
+bookmarks that are set by `bmkp-automatic-bookmark-set-function'. For
+example, if automatic bookmarking sets autonamed bookmarks, then
+`bmkp-autotemp-bookmark-predicates' should include
+`bmkp-autonamed-bookmark-p'.
+
+If you want the automatically created bookmarks to be highlighted,
+then customize option `bmkp-auto-light-when-set' to highlight
+bookmarks of the appropriate kind. For example, to highlight
+autonamed bookmarks set it to `autonamed-bookmark'.
+
+NOTE: This is the Emacs 20 version of `bmkp-automatic-bookmark-mode',
+which is global only, that is, all buffers are affected. If you
+instead want it to be local only, then do both of the following in
+your init file:
+ (make-variable-buffer-local 'bmkp-automatic-bookmark-mode)
+ (make-variable-buffer-local 'bmkp-automatic-bookmark-mode-timer)"
+ (interactive (list (or current-prefix-arg 'toggle)))
+ (setq bmkp-automatic-bookmark-mode (if (eq arg 'toggle)
+ (not bmkp-automatic-bookmark-mode)
+ (> (prefix-numeric-value arg) 0)))
+ (when bmkp-automatic-bookmark-mode-timer
+ (cancel-timer bmkp-automatic-bookmark-mode-timer)
+ (setq bmkp-automatic-bookmark-mode-timer nil))
+ (when bmkp-automatic-bookmark-mode
+ (setq bmkp-automatic-bookmark-mode-timer
+ (run-with-idle-timer bmkp-automatic-bookmark-mode-delay 'REPEAT
+ (lambda () ; This allows use as a local mode.
+ (when bmkp-automatic-bookmark-mode (bmkp-set-automatic-bookmark))))))
+ (when (interactive-p)
+ (message "Automatic bookmarking is now %s%s"
+ (if bmkp-automatic-bookmark-mode "ON" "OFF")
+ (if (local-variable-if-set-p 'bmkp-automatic-bookmark-mode)
+ (format " in buffer `%s'" (current-buffer))
+ ""))))
+
+
+ (add-to-list 'minor-mode-alist `(bmkp-automatic-bookmark-mode
+ ,bmkp-automatic-bookmark-mode-lighter))))
+
+(defun bmkp-not-near-other-automatic-bmks (&optional position)
+ "Is POSITION far enough from automatic bookmarks to create a new one?
+Return non-nil if `bmkp-automatic-bookmark-min-distance' is nil or if
+POSITION is at least `bmkp-automatic-bookmark-min-distance' chars from
+all other automatic bookmarks in the same buffer. Else return nil."
+ (unless position (setq position (point)))
+ (or (not bmkp-automatic-bookmark-min-distance)
+ (catch 'bmkp-not-near-other-automatic-bmks
+ (let (bmk-pos)
+ (dolist (bmk bmkp-automatic-bookmarks)
+ (when (and (bmkp-this-buffer-p bmk)
+ (setq bmk-pos (bookmark-get-position bmk))
+ (or (not bmk-pos) (< (abs (- position bmk-pos)) bmkp-automatic-bookmark-min-distance)))
+ (throw 'bmkp-not-near-other-automatic-bmks nil)))
+ t))))
+
+(defun bmkp-set-automatic-bookmark ()
+ "Invoke `bmkp-automatic-bookmark-set-function'.
+Do nothing if bookmark would be too near another automatic bookmark."
+ (when (bmkp-not-near-other-automatic-bmks)
+ (let ((bmkp-setting-automatic-bmk-p t)) (funcall bmkp-automatic-bookmark-set-function))))
+
+(when (> emacs-major-version 21) ; Emacs 22+ (need also `Info-selection-hook').
+
+ ;; Eval this so that even if the library is byte-compiled with Emacs 20,
+ ;; loading it into Emacs 22+ will define variable `bmkp-info-auto-bookmark-mode'.
+ (eval '(define-minor-mode bmkp-info-auto-bookmark-mode
+ "Toggle automatically setting a bookmark when you visit an Info node.
+The bookmark name is \"(MANUAL) `NODE'\", where:
+
+ MANUAL is the name of the current manual (the base file name).
+ NODE is the name of the current node.
+
+If option `bmkp-info-auto-type' is `create-or-update' then such a
+bookmark is created for the node if none exists. If the option value
+is `update-only' then no new bookmark is created automatically, but an
+existing bookmark is updated. (Updating a bookmark increments the
+recorded number of visits.) You can toggle the option using
+`\\[bmkp-toggle-info-auto-type]'."
+ :init-value nil :global t :group 'bookmark-plus :require 'bookmark+
+ :lighter bmkp-automatic-bookmark-mode-lighter
+ :link `(url-link :tag "Send Bug Report"
+ ,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
+Bookmark bug: \
+&body=Describe bug here, starting with `emacs -Q'. \
+Don't forget to mention your Emacs and library versions."))
+ :link '(url-link :tag "Download" "https://www.emacswiki.org/emacs/download/bookmark%2b.el")
+ :link '(url-link :tag "Description" "https://www.emacswiki.org/emacs/BookmarkPlus")
+ :link '(emacs-commentary-link :tag "Commentary" "bookmark+")
+ (if bmkp-info-auto-bookmark-mode
+ (add-hook 'Info-selection-hook 'bmkp-set-info-bookmark-with-node-name)
+ (remove-hook 'Info-selection-hook 'bmkp-set-info-bookmark-with-node-name))
+ (when (interactive-p)
+ (message "Automatic Info bookmarking is now %s" (if bmkp-info-auto-bookmark-mode "ON" "OFF")))))
+
+ (defun bmkp-set-info-bookmark-with-node-name (&optional nomsg)
+ "Maybe bookmark the current Info node using name \"(MANUAL) `NODE'\".
+MANUAL is the name of the current manual (the base file name).
+NODE is the name of the current node.
+
+If option `bmkp-info-auto-type' is `create-or-update' then a bookmark
+is created for the node if none exists. If it is `update-only' then
+no new bookmark is created automatically, but an existing bookmark is
+updated. You can use toggle `bmkp-info-auto-type' using
+`\\[bmkp-toggle-info-auto-type]'.
+
+Non-nil optional arg NOMSG means do not display a message saying that
+the node was bookmarked."
+ (interactive)
+ (when (and (derived-mode-p 'Info-mode) Info-current-node)
+ (save-excursion
+ (goto-char (point-min))
+ (let* ((bmk-name (and (stringp Info-current-file)
+ (format "(%s) %s" (file-name-sans-extension
+ (file-name-nondirectory Info-current-file))
+ Info-current-node)))
+ (bmk (bmkp-bookmark-record-from-name bmk-name 'NOERROR))
+ (visits (and bmk (bookmark-prop-get bmk 'visits))))
+ (when bmk-name
+ (cond ((and (not visits) (eq bmkp-info-auto-type 'create-or-update))
+ (bookmark-set bmk-name)
+ (unless nomsg (message "Created bookmark `%s' for Info node" bmk-name)))
+ (visits
+ (bmkp-record-visit bmk-name 'BATCHP)
+ (bmkp-refresh/rebuild-menu-list bmk-name nil)
+ (bmkp-maybe-save-bookmarks)
+ (unless nomsg (message "Updated bookmark `%s' for Info node" bmk-name)))))))))
+
+ (defun bmkp-toggle-info-auto-type (&optional msgp)
+ "Toggle the value of option `bmkp-info-auto-type'."
+ (interactive "p")
+ (setq bmkp-info-auto-type (if (eq bmkp-info-auto-type 'create-or-update) 'update-only 'create-or-update))
+ (when msgp (message "`bmkp-info-auto-bookmark-mode' now %s"
+ (if (eq bmkp-info-auto-type 'create-or-update)
+ "CREATES, as well as updates, Info bookmarks"
+ "only UPDATES EXISTING Info bookmarks"))))
+
+ )
+
+(if (fboundp 'define-minor-mode)
+ ;; Emacs 21 and later. Eval this so that even if the library is byte-compiled with Emacs 20,
+ ;; loading it into Emacs 21+ will define variable `bmkp-temporary-bookmarking-mode'.
+ (eval '(define-minor-mode bmkp-temporary-bookmarking-mode ; `M-L' in `*Bookmark List*'.
+ "Toggle temporary bookmarking.
+Temporary bookmarking means that any bookmark changes (creation,
+modification, deletion) are NOT automatically saved.
+
+Interactively, you are required to confirm turning on the mode.
+
+When the mode is turned ON:
+ a. `bookmark-save-flag' is set to nil.
+ b. `bmkp-current-bookmark-file' is set to a new, empty bookmark file
+ in directory `temporary-file-directory' (via `make-temp-file').
+ c. That file is not saved automatically.
+ d. In the `*Bookmark List*' display, the major-mode mode-line
+ indicator is set to `TEMPORARY ONLY'.
+
+Non-interactively, turn temporary bookmarking on if and only if ARG is
+positive. Non-interactively there is no prompt for confirmation."
+ :init-value nil :global t :group 'bookmark-plus :lighter bmkp-temporary-bookmarking-mode-lighter
+ :link `(url-link :tag "Send Bug Report"
+ ,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
+Bookmark bug: \
+&body=Describe bug here, starting with `emacs -Q'. \
+Don't forget to mention your Emacs and library versions."))
+ :link '(url-link :tag "Download" "https://www.emacswiki.org/emacs/download/bookmark%2b.el")
+ :link '(url-link :tag "Description" "https://www.emacswiki.org/emacs/BookmarkPlus")
+ :link '(emacs-commentary-link :tag "Commentary" "bookmark+")
+ (cond ((not bmkp-temporary-bookmarking-mode) ; Turn off.
+ (when (fboundp 'bmkp-unlight-bookmarks) ; In `bookmark+-lit.el'.
+ (bmkp-unlight-bookmarks ; Unhighlight the temporary (current) bookmarks.
+ '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays) nil))
+ (bmkp-switch-to-last-bookmark-file)
+ (setq bmkp-last-bookmark-file bmkp-current-bookmark-file) ; Forget last (temp file).
+ (when (interactive-p)
+ (message "Bookmarking is NOT temporary now. Restored previous bookmarks list")))
+ ((or (not (interactive-p))
+ (y-or-n-p (format "%switch to only temporary bookmarking? "
+ (if bookmark-save-flag "Save current bookmarks, then s" "S"))))
+ (when (and (> bookmark-alist-modification-count 0) bookmark-save-flag)
+ (bookmark-save))
+ (let ((new-file (make-temp-file "bmkp-temp-")))
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect new-file))
+ (goto-char (point-min))
+ (delete-region (point-min) (point-max)) ; In case a find-file hook inserted a header.
+ (if (boundp 'bookmark-file-coding-system) ; Emacs 25.2+
+ (bookmark-insert-file-format-version-stamp bookmark-file-coding-system)
+ (bookmark-insert-file-format-version-stamp))
+ (insert "(\n)"))
+ (bmkp-empty-file new-file)
+ (setq bmkp-last-as-first-bookmark-file nil) ; Prevent starting from a file of temp bmks.
+ (bookmark-load new-file t 'nosave) ; Saving was done just above.
+ (when bookmark-save-flag (bmkp-toggle-saving-bookmark-file (interactive-p))))
+ (when (interactive-p) (message "Bookmarking is now TEMPORARY")))
+ (t ; User refused to confirm.
+ (message "OK, canceled - bookmarking is NOT temporary")
+ (setq bmkp-temporary-bookmarking-mode nil)))))
+
+ ;; Emacs 20
+ (defun bmkp-temporary-bookmarking-mode (&optional arg) ; `M-L' in `*Bookmark List*'.
+ "Toggle temporary bookmarking.
+Temporary bookmarking means that any bookmark changes (creation,
+modification, deletion) are NOT automatically saved.
+
+Interactively, you are required to confirm turning on the mode.
+
+When the mode is turned ON:
+ a. `bookmark-save-flag' is set to nil.
+ b. `bmkp-current-bookmark-file' is set to a new, empty bookmark file
+ in directory `temporary-file-directory' (via `make-temp-file').
+ c. That file is not saved automatically.
+ d. In the `*Bookmark List*' display, the major-mode mode-line
+ indicator is set to `TEMPORARY ONLY'.
+
+Non-interactively, turn temporary bookmarking on if and only if ARG is
+positive. Non-interactively there is no prompt for confirmation."
+ (interactive "P")
+ (setq bmkp-temporary-bookmarking-mode
+ (if arg (> (prefix-numeric-value arg) 0) (not bmkp-temporary-bookmarking-mode)))
+ (cond ((not bmkp-temporary-bookmarking-mode) ; Turn off.
+ (when (fboundp 'bmkp-unlight-bookmarks) ; In `bookmark+-lit.el'.
+ (bmkp-unlight-bookmarks ; Unhighlight the temporary (current) bookmarks.
+ '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays) nil))
+ (bmkp-switch-to-last-bookmark-file)
+ (setq bmkp-last-bookmark-file bmkp-current-bookmark-file) ; Forget last (temporary file).
+ (run-hooks 'bmkp-temporary-bookmarking-mode-hook)
+ (when (interactive-p)
+ (message "Bookmarking is NOT temporary now. Restored previous bookmarks list")))
+ ((or (not (interactive-p))
+ (y-or-n-p (format "%switch to only TEMPORARY bookmarking? "
+ (if bookmark-save-flag "Save current bookmarks, then s" "S"))))
+ (when (and (> bookmark-alist-modification-count 0) bookmark-save-flag)
+ (bookmark-save))
+ (let ((new-file (make-temp-file "bmkp-temp-")))
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect new-file))
+ (goto-char (point-min))
+ (delete-region (point-min) (point-max)) ; In case a find-file hook inserted a header, etc.
+ (bookmark-insert-file-format-version-stamp)
+ (insert "(\n)"))
+ (bmkp-empty-file new-file)
+ (bookmark-load new-file t 'nosave) ; Saving was done just above.
+ (when bookmark-save-flag (bmkp-toggle-saving-bookmark-file (interactive-p))))
+ (run-hooks 'bmkp-temporary-bookmarking-mode-hook)
+ (when (interactive-p) (message "Bookmarking is now TEMPORARY")))
+ (t ; User refused to confirm.
+ (message "OK, canceled - bookmarking is NOT temporary")
+ (setq bmkp-temporary-bookmarking-mode nil))))
+
+
+ (add-to-list 'minor-mode-alist `(bmkp-temporary-bookmarking-mode
+ ,bmkp-temporary-bookmarking-mode-lighter)))
+
+;;;###autoload (autoload 'bmkp-toggle-autotemp-on-set "bookmark+")
+(defun bmkp-toggle-autotemp-on-set (&optional msg-p) ; Bound to `C-x x x'
+ "Toggle automatically making any bookmark temporary whenever it is set.
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive "p")
+ (setq bmkp-autotemp-all-when-set-p (not bmkp-autotemp-all-when-set-p))
+ (when msg-p (message "Automatically making bookmarks temporary when set is now %s"
+ (if bmkp-autotemp-all-when-set-p "ON" "OFF"))))
+
+;;;###autoload (autoload 'bmkp-toggle-temporary-bookmark "bookmark+")
+(defun bmkp-toggle-temporary-bookmark (bookmark &optional msg-p)
+ "Toggle whether BOOKMARK is temporary (not saved to disk).
+Return the full updated bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) 'MSG))
+ (let ((was-temp (bmkp-temporary-bookmark-p bookmark)))
+ (bookmark-prop-set bookmark 'bmkp-temp (not was-temp))
+ (when msg-p (message "Bookmark `%s' is now %s"
+ (if (stringp bookmark) bookmark (bmkp-bookmark-name-from-record bookmark))
+ (if was-temp "SAVABLE" "TEMPORARY"))))
+ bookmark)
+
+;;;###autoload (autoload 'bmkp-make-bookmark-temporary "bookmark+")
+(defun bmkp-make-bookmark-temporary (bookmark &optional msg-p)
+ "Make BOOKMARK temporary (not saved to disk).
+Return the full updated bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) 'MSG))
+ (bookmark-prop-set bookmark 'bmkp-temp t)
+ (when msg-p (message "Bookmark `%s' is now TEMPORARY"
+ (if (stringp bookmark) bookmark (bmkp-bookmark-name-from-record bookmark))))
+ bookmark)
+
+;;;###autoload (autoload 'bmkp-make-bookmark-savable "bookmark+")
+(defun bmkp-make-bookmark-savable (bookmark &optional msg-p)
+ "Make BOOKMARK savable to disk (not temporary).
+Return the full updated bookmark.
+BOOKMARK is a bookmark name or a bookmark record.
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive (list (bookmark-completing-read "Bookmark" (bmkp-default-bookmark-name)) 'MSG))
+ (bookmark-prop-set bookmark 'bmkp-temp nil)
+ (when msg-p (message "Bookmark `%s' is now SAVABLE"
+ (if (stringp bookmark) bookmark (bmkp-bookmark-name-from-record bookmark))))
+ bookmark)
+
+;;;###autoload (autoload 'bmkp-delete-all-temporary-bookmarks "bookmark+")
+(defun bmkp-delete-all-temporary-bookmarks (&optional msg-p)
+ "Delete all temporary bookmarks, after confirmation.
+These are bookmarks that are `bmkp-temporary-bookmark-p'. You can
+make a bookmark temporary using `bmkp-make-bookmark-temporary' or
+`bmkp-toggle-temporary-bookmark'.
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive "p")
+ (let ((bmks-to-delete (mapcar #'bmkp-bookmark-name-from-record (bmkp-temporary-alist-only))))
+ (if (null bmks-to-delete)
+ (when msg-p (message "No temporary bookmarks to delete"))
+ (when (and msg-p (not (y-or-n-p (format "Delete ALL temporary bookmarks? "))))
+ (error "OK - delete canceled"))
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bmk bmks-to-delete) (bookmark-delete bmk 'BATCHP))) ; No refresh yet.
+ (bmkp-refresh/rebuild-menu-list nil (not msg-p)) ; Now refresh, after iterate.
+ (when msg-p (message "Deleted all temporary bookmarks")))))
+
+;; You can use this in `kill-emacs-hook'.
+(defun bmkp-delete-temporary-no-confirm ()
+ "Delete all temporary bookmarks, without confirmation."
+ (when (and bookmarks-already-loaded bookmark-alist)
+ (let ((bmks-to-delete (mapcar #'bmkp-bookmark-name-from-record (bmkp-temporary-alist-only)))
+ (bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bmk bmks-to-delete) (bookmark-delete bmk 'BATCHP))) ; No refresh yet.
+ (bmkp-refresh/rebuild-menu-list nil 'BATCHP))) ; Now refresh, after iterate.
+
+;;;###autoload (autoload 'bmkp-delete-bookmarks "bookmark+")
+(defun bmkp-delete-bookmarks (&optional position allp alist msg-p) ; Bound to `C-x x delete'
+ "Delete some bookmarks at point or all bookmarks in the buffer.
+With no prefix argument, delete some bookmarks at point.
+If there is more than one, require confirmation for each.
+
+With a prefix argument, delete *ALL* bookmarks in the current buffer.
+
+Non-interactively:
+* Delete at POSITION, not point. If nil, delete at point.
+* Non-nil optional arg ALLP means delete all bookmarks in the buffer.
+* ALIST is the alist of bookmarks.
+ If nil, use the bookmarks in the current buffer.
+* Non-nil MSG-P means display informative messages."
+ (interactive "d\nP\ni\np")
+ (unless position (setq position (point)))
+ (let ((bmks-to-delete (and allp (mapcar #'bmkp-bookmark-name-from-record (bmkp-this-buffer-alist-only))))
+ (bmks-deleted ())
+ bmk-pos)
+ (when (and msg-p bmks-to-delete (not (y-or-n-p (format "Delete ALL bookmarks in buffer `%s'? "
+ (buffer-name)))))
+ (error "Canceled - no bookmarks deleted"))
+ (cond (bmks-to-delete ; Delete all.
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bname bmks-to-delete) (bookmark-delete bname 'BATCHP))) ; No refresh yet.
+ (bmkp-refresh/rebuild-menu-list nil (not msg-p)) ; Refresh now, after iterate.
+ (when msg-p (message "Deleted all bookmarks in buffer `%s'" (buffer-name))))
+
+ (allp ; Requested ALLP, but there are none. (No-op if not interactive.)
+ (when msg-p (message "No bookmarks to delete in buffer `%s'" (buffer-name))))
+
+ (t ; Delete selected bookmarks at point.
+ (let (bname)
+ (dolist (bmk (or alist (bmkp-this-buffer-alist-only)))
+ (when (eq position (setq bmk-pos (bookmark-get-position bmk)))
+ (setq bname (bmkp-bookmark-name-from-record bmk))
+ ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+ (unless (memq bname bmks-to-delete)
+ (setq bmks-to-delete (cons bname bmks-to-delete)))))
+ (cond ((cadr bmks-to-delete) ; More than one at point.
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bname bmks-to-delete)
+ (when (or (not msg-p) (y-or-n-p (format "Delete bookmark `%s'? " bname)))
+ (bookmark-delete bname 'BATCHP) ; No refresh yet.
+ ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
+ (unless (memq bname bmks-deleted) (setq bmks-deleted (cons bname bmks-deleted))))))
+ (bmkp-refresh/rebuild-menu-list nil (not msg-p)) ; Refresh now.
+ (when msg-p
+ (message (if bmks-deleted
+ (format "Deleted bookmarks: %s"
+ (mapconcat (lambda (bname) (format "`%s'" bname)) bmks-deleted
+ ", "))
+ "No bookmarks deleted"))))
+ (bmks-to-delete ; Only one bookmark at point.
+ (bookmark-delete (car bmks-to-delete))
+ (when msg-p (message "Deleted bookmark `%s'" (car bmks-to-delete))))
+ (t
+ (when msg-p (message "No bookmarks at point to delete")))))))))
+
+;; Because of Emacs bug #19915, we need to use `advice-add' for `org-store-link', so this feature
+;; is available only for Emacs 24.4+.
+(when (fboundp 'advice-add)
+
+ (defvar bmkp-store-org-link-checking-p nil
+ "Whether `bmkp-(bmenu-)store-org-link(-1)' call is checking applicability.")
+
+ (defun bmkp-store-org-link (arg)
+ "Store a link to a bookmark for insertion in an Org-mode buffer.
+You are prompted for the bookmark name.
+
+If you use a numeric prefix arg then the bookmark will be jumped to in
+the same window. Without a numeric prefix arg, the link will use
+another window. The link type is `bookmark' or `bookmark-other-win',
+respectively."
+ (interactive "P")
+ (require 'org)
+ (let ((org-store-link-functions (append org-store-link-functions '(bmkp-store-org-link-1))))
+ (call-interactively #'org-store-link)))
+
+ (defun bmkp-store-org-link-1 ()
+ "Store a link to a bookmark for insertion in an Org-mode buffer.
+See command `bmkp-store-org-link'."
+ (setq bmkp-store-org-link-checking-p (not bmkp-store-org-link-checking-p))
+ (require 'org)
+ (or bmkp-store-org-link-checking-p ; Non-nil return is all that is needed for checking.
+ (let* ((other-win (and current-prefix-arg (not (consp current-prefix-arg))))
+ (bmk (bmkp-completing-read-lax
+ (format "Store %sOrg link for bookmark" (if other-win "other-window " ""))))
+ (link (format "bookmark%s:%s" (if other-win "-other-win" "") bmk))
+ (bmk-desc (format "Bookmark: %s" bmk)))
+ (org-store-link-props :type "bookmark" :link link :description bmk-desc))))
+
+ (advice-add 'org-store-link :before #'bmkp-reset-bmkp-store-org-link-checking-p)
+ (defun bmkp-reset-bmkp-store-org-link-checking-p (&rest _IGNORE)
+ "Reset `bmkp-store-org-link-checking-p' to nil."
+ (setq bmkp-store-org-link-checking-p nil)))
+
+(defun bmkp-ffap-guesser ()
+ "`ffap-guesser', but deactivate a large active region first."
+ (and (require 'ffap nil t)
+ ;; Prevent using a large active region to guess ffap: Emacs bug #25243.
+ (let ((mark-active (and mark-active (< (buffer-size) bmkp-ffap-max-region-size))))
+ (ffap-guesser))))
+
+;; Same as `icicle-thing-at-point'.
+(defun bmkp-thing-at-point (thing &optional syntax-table)
+ "`thingatpt+.el' version of `thing-at-point', if possible.
+`tap-thing-at-point' if defined, else `thing-at-point'.
+if non-nil, set SYNTAX-TABLE for the duration."
+ (if (fboundp 'tap-thing-at-point)
+ (tap-thing-at-point thing syntax-table)
+ (if (and (syntax-table-p syntax-table) (fboundp 'with-syntax-table)) ; Emacs 21+.
+ (with-syntax-table syntax-table (thing-at-point thing))
+ (thing-at-point thing)))) ; Ignore any SYNTAX-TABLE arg for Emacs 20, for vanilla.
+
+(defun bmkp-get-external-annotation (annotation)
+ "Return a cons (DESTINATION . TYPE) for ANNOTATION.
+DESTINATION is a string naming a file, a URL, or a bookmark.
+TYPE is `FILE', `URL', or `BOOKMARK', accordingly."
+ (cond ((string-match "\\`\\s-*bmkp-annot-file:\\s-*\"\\(\.+\\)\"" annotation)
+ (cons (match-string 1 annotation) 'FILE))
+ ((string-match "\\`\\s-*bmkp-annot-url:\\s-*\"\\(\.+\\)\"" annotation)
+ (cons (match-string 1 annotation) 'URL))
+ ((string-match "\\`\\s-*bmkp-annot-bmk:\\s-*\"\\(\.+\\)\"" annotation)
+ (cons (match-string 1 annotation) 'BOOKMARK))
+ (t nil)))
+
+(defun bmkp-visit-external-annotation (annotation.type msg-p)
+ "Visit the external annotation represented by ANNOTATION.TYPE.
+The first arg is a cons as returned by `bmkp-get-external-annotation'.
+I MSG-P is non-nil then echo the annotation type."
+ (let ((ann (car annotation.type))
+ (type (cdr annotation.type)))
+ (case type
+ (FILE (find-file-other-window ann))
+ (URL (browse-url ann))
+ (BOOKMARK (bookmark-jump-other-window ann))
+ (otherwise (error "`bmkp-visit-external-annotation': Bad annotation type: `%S'" type)))
+ (message "Showing external annotation of type %s" type) (sit-for 1)))
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(provide 'bookmark+-1)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; bookmark+-1.el ends here
--- /dev/null
+;;; bookmark+-bmu.el --- Bookmark+ code for the `*Bookmark List*' (bmenu).
+;;
+;; Filename: bookmark+-bmu.el
+;; Description: Bookmark+ code for the `*Bookmark List*' (bmenu).
+;; Author: Drew Adams, Thierry Volpiatto
+;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com")
+;; Copyright (C) 2000-2022, Drew Adams, all rights reserved.
+;; Copyright (C) 2009, Thierry Volpiatto, all rights reserved.
+;; Created: Mon Jul 12 09:05:21 2010 (-0700)
+;; Last-Updated: Fri Jan 14 12:40:58 2022 (-0800)
+;; By: dradams
+;; Update #: 4177
+;; URL: https://www.emacswiki.org/emacs/download/bookmark%2b-bmu.el
+;; Doc URL: https://www.emacswiki.org/emacs/BookmarkPlus
+;; Keywords: bookmarks, bookmark+, placeholders, annotations, search, info, url, eww, w3m, gnus
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x, 26.x
+;;
+;; Features that might be required by this library:
+;;
+;; `apropos', `apropos+', `avoid', `backquote', `bookmark',
+;; `bookmark+', `bookmark+-1', `bookmark+-bmu', `bookmark+-key',
+;; `bookmark+-lit', `button', `bytecomp', `cconv', `cl', `cl-lib',
+;; `cmds-menu', `col-highlight', `crosshairs', `fit-frame',
+;; `font-lock', `font-lock+', `frame-fns', `gv', `help+',
+;; `help-fns', `help-fns+', `help-macro', `help-macro+',
+;; `help-mode', `hl-line', `hl-line+', `info', `info+', `kmacro',
+;; `macroexp', `menu-bar', `menu-bar+', `misc-cmds', `misc-fns',
+;; `naked', `pp', `pp+', `radix-tree', `rect', `replace',
+;; `second-sel', `strings', `syntax', `text-mode', `thingatpt',
+;; `thingatpt+', `vline', `w32browser-dlgopen', `wid-edit',
+;; `wid-edit+'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; This library contains code for buffer `*Bookmark List*' (mode
+;; `bookmark-bmenu-mode').
+;;
+;; The Bookmark+ libraries are these:
+;;
+;; `bookmark+.el' - main (driver) library
+;; `bookmark+-mac.el' - Lisp macros
+;; `bookmark+-lit.el' - (optional) code for highlighting bookmarks
+;; `bookmark+-bmu.el' - code for the `*Bookmark List*' (this file)
+;; `bookmark+-1.el' - other required code (non-bmenu)
+;; `bookmark+-key.el' - key and menu bindings
+;;
+;; `bookmark+-doc.el' - documentation (comment-only file)
+;; `bookmark+-chg.el' - change log (comment-only file)
+;;
+;; The documentation (in `bookmark+-doc.el') includes how to
+;; byte-compile and install Bookmark+. The documentation is also
+;; available in these ways:
+;;
+;; 1. From the bookmark list (`C-x r l'):
+;; Use `?' to show the current bookmark-list status and general
+;; help, then click link `Doc in Commentary' or link `Doc on the
+;; Web'.
+;;
+;; 2. From the Emacs-Wiki Web site:
+;; https://www.emacswiki.org/emacs/BookmarkPlus.
+;;
+;; 3. From the Bookmark+ group customization buffer:
+;; `M-x customize-group bookmark-plus', then click link
+;; `Commentary'.
+;;
+;; (The commentary links in #1 and #3 work only if you have library
+;; `bookmark+-doc.el' in your `load-path'.)
+
+;;(@> "Index")
+;;
+;; Index
+;; -----
+;;
+;; If you have library `linkd.el' and Emacs 22 or later, load
+;; `linkd.el' and turn on `linkd-mode' now. It lets you easily
+;; navigate around the sections of this doc. Linkd mode will
+;; highlight this Index, as well as the cross-references and section
+;; headings throughout this file. You can get `linkd.el' here:
+;; https://www.emacswiki.org/emacs/download/linkd.el.
+;;
+;; (@> "Things Defined Here")
+;; (@> "Utility Functions")
+;; (@> "Faces (Customizable)")
+;; (@> "User Options (Customizable)")
+;; (@> "Internal Variables")
+;; (@> "Compatibility Code for Older Emacs Versions")
+;; (@> "Menu List Replacements (`bookmark-bmenu-*')")
+;; (@> "Bookmark+ Functions (`bmkp-*')")
+;; (@> "Menu-List (`*-bmenu-*') Filter Commands")
+;; (@> "Menu-List (`*-bmenu-*') Commands Involving Marks")
+;; (@> "Omitted Bookmarks")
+;; (@> "Search-and-Replace Locations of Marked Bookmarks")
+;; (@> "Tags")
+;; (@> "General Menu-List (`-*bmenu-*') Commands and Functions")
+;; (@> "Sorting - Commands")
+;; (@> "Other Bookmark+ Functions (`bmkp-*')")
+;; (@> "Keymaps")
+
+;;(@* "Things Defined Here")
+;;
+;; Things Defined Here
+;; -------------------
+;;
+;; Commands defined here:
+;;
+;; `bmkp-bmenu-add-tags', `bmkp-bmenu-add-tags-to-marked',
+;; `bmkp-bmenu-change-sort-order',
+;; `bmkp-bmenu-change-sort-order-repeat',
+;; `bmkp-bmenu-clone-bookmark', `bmkp-bmenu-copy-bookmark',
+;; `bmkp-bmenu-copy-marked-to-bookmark-file',
+;; `bmkp-bmenu-copy-tags',
+;; `bmkp-bmenu-create-bookmark-file-from-marked',
+;; `bmkp-bmenu-define-command',
+;; `bmkp-bmenu-define-full-snapshot-command',
+;; `bmkp-bmenu-define-jump-marked-command',
+;; `bmkp-bmenu-delete-marked', `bmkp-bmenu-describe-marked',
+;; `bmkp-bmenu-describe-this+move-down',
+;; `bmkp-bmenu-describe-this+move-up',
+;; `bmkp-bmenu-describe-this-bookmark',`bmkp-bmenu-dired-marked',
+;; `bmkp-bmenu-edit-annotations-for-marked',
+;; `bmkp-bmenu-edit-bookmark-name-and-location',
+;; `bmkp-bmenu-filter-annotation-incrementally',
+;; `bmkp-bmenu-filter-bookmark-name-incrementally',
+;; `bmkp-bmenu-filter-file-name-incrementally',
+;; `bmkp-bmenu-filter-tags-incrementally',
+;; `bmkp-bmenu-flag-for-deletion',
+;; `bmkp-bmenu-flag-for-deletion-backwards',
+;; `bmkp-bmenu-isearch-marked-bookmarks' (Emacs 23+),
+;; `bmkp-bmenu-isearch-marked-bookmarks-regexp' (Emacs 23+),
+;; `bmkp-bmenu-jump-to-marked', `bmkp-bmenu-load-marking',
+;; `bmkp-bmenu-load-marking-unmark-first',
+;; `bmkp-bmenu-make-sequence-from-marked', `bmkp-bmenu-mark-all',
+;; `bmkp-bmenu-mark-autofile-bookmarks',
+;; `bmkp-bmenu-mark-bookmark-file-bookmarks',
+;; `bmkp-bmenu-mark-bookmark-list-bookmarks',
+;; `bmkp-bmenu-mark-bookmarks-satisfying',
+;; `bmkp-bmenu-mark-bookmarks-tagged-all',
+;; `bmkp-bmenu-mark-bookmarks-tagged-none',
+;; `bmkp-bmenu-mark-bookmarks-tagged-not-all',
+;; `bmkp-bmenu-mark-bookmarks-tagged-regexp',
+;; `bmkp-bmenu-mark-bookmarks-tagged-some',
+;; `bmkp-bmenu-mark-desktop-bookmarks',
+;; `bmkp-bmenu-mark-dired-bookmarks',
+;; `bmkp-bmenu-mark-eww-bookmarks' (Emacs 25+),
+;; `bmkp-bmenu-mark-file-bookmarks',
+;; `bmkp-bmenu-mark-function-bookmarks',
+;; `bmkp-bmenu-mark-gnus-bookmarks',
+;; `bmkp-bmenu-mark-icicles-search-hits-bookmarks',
+;; `bmkp-bmenu-mark-image-bookmarks',
+;; `bmkp-bmenu-mark-info-bookmarks',
+;; `bmkp-bmenu-mark-lighted-bookmarks',
+;; `bmkp-bmenu-mark-man-bookmarks',
+;; `bmkp-bmenu-mark-non-file-bookmarks',
+;; `bmkp-bmenu-mark-non-invokable-bookmarks',
+;; `bmkp-bmenu-mark-orphaned-local-file-bookmarks',
+;; `bmkp-bmenu-mark-region-bookmarks',
+;; `bmkp-bmenu-mark-snippet-bookmarks',
+;; `bmkp-bmenu-mark-specific-buffer-bookmarks',
+;; `bmkp-bmenu-mark-specific-file-bookmarks',
+;; `bmkp-bmenu-mark-url-bookmarks',
+;; `bmkp-bmenu-mark-variable-list-bookmarks',
+;; `bmkp-bmenu-mark-w3m-bookmarks', `bmkp-bmenu-mouse-3-menu',
+;; `bmkp-bmenu-mode-status-help',
+;; `bmkp-bmenu-move-marked-to-bookmark-file',
+;; `bmkp-bmenu-nb-marked-in-mode-name', `bmkp-bmenu-omit',
+;; `bmkp-bmenu-omit-marked', `bmkp-bmenu-omit/unomit-marked',
+;; `bmkp-bmenu-paste-add-tags',
+;; `bmkp-bmenu-paste-add-tags-to-marked',
+;; `bmkp-bmenu-paste-replace-tags',
+;; `bmkp-bmenu-paste-replace-tags-for-marked',
+;; `bmkp-bmenu-query-replace-marked-bookmarks-regexp',
+;; `bmkp-bmenu-quit', `bmkp-bmenu-refresh-menu-list',
+;; `bmkp-bmenu-regexp-mark', `bookmark-bmenu-relocate' (Emacs 20,
+;; 21), `bmkp-bmenu-relocate-marked', `bmkp-bmenu-remove-all-tags',
+;; `bmkp-bmenu-remove-tags', `bmkp-bmenu-remove-tags-from-marked',
+;; `bmkp-bmenu-search-marked-bookmarks-regexp',
+;; `bmkp-bmenu-set-bookmark-file-bookmark-from-marked',
+;; `bmkp-bmenu-set-tag-value',
+;; `bmkp-bmenu-set-tag-value-for-marked', `bmkp-bmenu-show-all',
+;; `bmkp-bmenu-show-only-autofile-bookmarks',
+;; `bmkp-bmenu-show-only-autonamed-bookmarks',
+;; `bmkp-bmenu-show-only-bookmark-file-bookmarks',
+;; `bmkp-bmenu-show-only-bookmark-list-bookmarks',
+;; `bmkp-bmenu-show-only-desktop-bookmarks',
+;; `bmkp-bmenu-show-only-dired-bookmarks',
+;; `bmkp-bmenu-show-only-eww-bookmarks' (Emacs 25+),
+;; `bmkp-bmenu-show-only-file-bookmarks',
+;; `bmkp-bmenu-show-only-function-bookmarks',
+;; `bmkp-bmenu-show-only-gnus-bookmarks',
+;; `bmkp-bmenu-show-only-icicles-search-hits-bookmarks.',
+;; `bmkp-bmenu-show-only-image-bookmarks',
+;; `bmkp-bmenu-show-only-info-bookmarks',
+;; `bmkp-bmenu-show-only-man-bookmarks',
+;; `bmkp-bmenu-show-only-non-file-bookmarks',
+;; `bmkp-bmenu-show-only-non-invokable-bookmarks',
+;; `bmkp-bmenu-show-only-omitted-bookmarks',
+;; `bmkp-bmenu-show-only-orphaned-local-file-bookmarks',
+;; `bmkp-bmenu-show-only-region-bookmarks',
+;; `bmkp-bmenu-show-only-snippet-bookmarks',
+;; `bmkp-bmenu-show-only-specific-buffer-bookmarks',
+;; `bmkp-bmenu-show-only-specific-file-bookmarks',
+;; `bmkp-bmenu-show-only-temporary-bookmarks',
+;; `bmkp-bmenu-show-only-tagged-bookmarks',
+;; `bmkp-bmenu-show-only-untagged-bookmarks',
+;; `bmkp-bmenu-show-only-url-bookmarks',
+;; `bmkp-bmenu-show-only-variable-list-bookmarks',
+;; `bmkp-bmenu-show-only-w3m-bookmarks',
+;; `bmkp-bmenu-show-or-edit-annotation',
+;; `bmkp-bmenu-show-this-annotation+move-down',
+;; `bmkp-bmenu-show-this-annotation+move-up',
+;; `bmkp-bmenu-sort-annotated-before-unannotated',
+;; `bmkp-bmenu-sort-by-bookmark-name',
+;; `bmkp-bmenu-sort-by-bookmark-visit-frequency',
+;; `bmkp-bmenu-sort-by-bookmark-type',
+;; `bmkp-bmenu-sort-by-creation-time',
+;; `bmkp-bmenu-sort-by-file-name',
+;; `bmkp-bmenu-sort-by-Gnus-thread',
+;; `bmkp-bmenu-sort-by-Info-node-name',
+;; `bmkp-bmenu-sort-by-Info-position',
+;; `bmkp-bmenu-sort-by-last-bookmark-access',
+;; `bmkp-bmenu-sort-by-last-buffer-or-file-access',
+;; `bmkp-bmenu-sort-by-last-local-file-access',
+;; `bmkp-bmenu-sort-by-last-local-file-update',
+;; `bmkp-bmenu-sort-by-local-file-size',
+;; `bmkp-bmenu-sort-by-local-file-type', `bmkp-bmenu-sort-by-url',
+;; `bmkp-bmenu-sort-flagged-before-unflagged',
+;; `bmkp-bmenu-sort-marked-before-unmarked',
+;; `bmkp-bmenu-sort-modified-before-unmodified',
+;; `bmkp-bmenu-sort-tagged-before-untagged',
+;; `bmkp-bmenu-toggle-marked-temporary/savable',
+;; `bmkp-bmenu-toggle-marks', `bmkp-bmenu-toggle-show-only-marked',
+;; `bmkp-bmenu-toggle-show-only-unmarked',
+;; `bmkp-bmenu-toggle-temporary', `bmkp-bmenu-unmark-all',
+;; `bmkp-bmenu-unmark-bookmarks-tagged-all',
+;; `bmkp-bmenu-unmark-bookmarks-tagged-none',
+;; `bmkp-bmenu-unmark-bookmarks-tagged-not-all',
+;; `bmkp-bmenu-unmark-bookmarks-tagged-regexp',
+;; `bmkp-bmenu-unmark-bookmarks-tagged-some',
+;; `bmkp-bmenu-unomit-marked', `bmkp-bmenu-w32-open',
+;; `bmkp-bmenu-w32-open-select', `bmkp-bmenu-w32-open-with-mouse',
+;; `bmkp-define-tags-sort-command'.
+;;
+;; Faces defined here:
+;;
+;; `bmkp-*-mark', `bmkp->-mark', `bmkp-a-mark',
+;; `bmkp-bad-bookmark', `bmkp-bookmark-file', `bmkp-bookmark-list',
+;; `bmkp-buffer', `bmkp-D-mark', `bmkp-desktop',
+;; `bmkp-file-handler', `bmkp-function', `bmkp-gnus',
+;; `bmkp-heading', `bmkp-info', `bmkp-local-directory',
+;; `bmkp-local-file-with-region', `bmkp-local-file-without-region',
+;; `bmkp-man', `bmkp-no-jump', `bmkp-no-local', `bmkp-non-file',
+;; `bmkp-remote-file', `bmkp-sequence', `bmkp-snippet',
+;; `bmkp-su-or-sudo', `bmkp-t-mark', `bmkp-url',
+;; `bmkp-variable-list', `bmkp-X-mark'.
+;;
+;; User options defined here:
+;;
+;; `bmkp-bmenu-commands-file',
+;; `bmkp-bmenu-image-bookmark-icon-file',
+;; `bmkp-bmenu-omitted-bookmarks', `bmkp-bmenu-state-file',
+;; `bmkp-propertize-bookmark-names-flag', `bmkp-sort-orders-alist',
+;; `bmkp-sort-orders-for-cycling-alist'.
+;;
+;; Non-interactive functions defined here:
+;;
+;; `bmkp--pop-to-buffer-same-window', `bmkp-assoc-delete-all',
+;; `bmkp-bmenu-barf-if-not-in-menu-list',
+;; `bmkp-bmenu-cancel-incremental-filtering',
+;; `bmkp-bmenu-filter-alist-by-annotation-regexp',
+;; `bmkp-bmenu-filter-alist-by-bookmark-name-regexp',
+;; `bmkp-bmenu-filter-alist-by-file-name-regexp',
+;; `bmkp-bmenu-filter-alist-by-tags-regexp',
+;; `bmkp-bmenu-get-marked-files', `bmkp-bmenu-goto-bookmark-named',
+;; `bmkp-bmenu-kill-annotation', `bmkp-bmenu-list-1',
+;; `bmkp-bmenu-mark/unmark-bookmarks-tagged-all/none',
+;; `bmkp-bmenu-mark/unmark-bookmarks-tagged-some/not-all',
+;; `bmkp-bmenu-mode-line', `bmkp-bmenu-mode-line-string',
+;; `bmkp-bmenu-propertize-item', `bmkp-bmenu-read-filter-input',
+;; `bmkp-bmenu-store-org-link' (Emacs 24.4+),
+;; `bmkp-bookmark-data-from-record',
+;; `bmkp-bookmark-name-from-record', `bmkp-face-prop',
+;; `bmkp-bmenu-marked-or-this-or-all', `bmkp-looking-at-p',
+;; `bmkp-maybe-unpropertize-bookmark-names',
+;; `bmkp-maybe-unpropertize-string', `bmkp-remap',
+;; `bmkp-replace-regexp-in-string',
+;; `bmkp-reverse-multi-sort-order', `bmkp-reverse-sort-order',
+;; `bmkp-string-match-p', `bookmark-name-from-full-record',
+;; `bookmark-name-from-record',
+;;
+;; Internal variables defined here:
+;;
+;; `bmkp-bmenu-before-hide-marked-alist',
+;; `bmkp-bmenu-before-hide-unmarked-alist',
+;; `bmkp-bmenu-bookmark-file-menu',
+;; `bmkp-bmenu-define-command-history',
+;; `bmkp-bmenu-define-command-menu', `bmkp-bmenu-delete-menu',
+;; `bmkp-bmenu-filter-function', `bmkp-bmenu-filter-pattern',
+;; `bmkp-bmenu-filter-timer', `bmkp-bmenu-first-time-p',
+;; `bmkp-bmenu-header-lines', `bmkp-bmenu-highlight-menu',
+;; `bmkp-bmenu-line-overlay', `bmkp-bmenu-mark-menu',
+;; `bmkp-bmenu-marked-bookmarks', `bmkp-bmenu-marks-width',
+;; `bmkp-bmenu-mark-types-menu', `bmkp-bmenu-menubar-menu',
+;; `bmkp-bmenu-omit-menu', `bmkp-bmenu-search-menu',
+;; `bmkp-bmenu-show-menu',
+;; `bmkp-bmenu-show-types-menu',`bmkp-bmenu-sort-menu',
+;; `bmkp-bmenu-tags-menu', `bmkp-bmenu-title',
+;; `bmkp-bmenu-toggle-menu', `bmkp-flagged-bookmarks',
+;; `bmkp-last-bmenu-bookmark'.
+;;
+;;
+;; ***** NOTE: The following commands defined in `bookmark.el'
+;; have been REDEFINED HERE:
+;;
+;; `bookmark-bmenu-execute-deletions', `bookmark-bmenu-list',
+;; `bookmark-bmenu-mark', `bookmark-bmenu-1-window',
+;; `bookmark-bmenu-2-window', `bookmark-bmenu-other-frame',
+;; `bookmark-bmenu-other-window',
+;; `bookmark-bmenu-other-window-with-mouse',
+;; `bookmark-bmenu-rename', `bookmark-bmenu-show-annotation',
+;; `bookmark-bmenu-switch-other-window',
+;; `bookmark-bmenu-this-window', `bookmark-bmenu-toggle-filenames',
+;; `bookmark-bmenu-unmark'.
+;;
+;;
+;; ***** NOTE: The following non-interactive functions and macros
+;; defined in `bookmark.el' have been REDEFINED HERE:
+;;
+;; `bookmark-bmenu-bookmark', `bookmark-bmenu-check-position',
+;; `bookmark-bmenu-delete', `bookmark-bmenu-delete-backwards',
+;; `bookmark-bmenu-ensure-position' (Emacs 23.2+),
+;; `bookmark-bmenu-hide-filenames', `bookmark-bmenu-mode',
+;; `bookmark-bmenu-show-filenames',
+;; `bookmark-bmenu-surreptitiously-rebuild-list',
+;; `with-buffer-modified-unmodified' (Emacs < 23.2).
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(eval-when-compile (require 'cl)) ;; case (plus, for Emacs 20: dolist, push)
+(eval-when-compile (require 'easymenu)) ;; easy-menu-create-menu
+(eval-when-compile (require 'org nil t)) ;; org-add-link-type
+
+(require 'bookmark)
+;; bookmark-alist, bookmark-bmenu-file-column,
+;; bookmark-bmenu-hidden-bookmarks, bookmark-bmenu-mode-map,
+;; bookmark-bmenu-select, bookmark-get-annotation,
+;; bookmark-get-filename, bookmark-get-handler, bookmark-kill-line,
+;; bookmark-maybe-load-default-file, bookmark-name-from-full-record,
+;; bookmark-name-from-record, bookmark-prop-get
+
+
+;; Some general Renamings.
+;;
+;; 1. Fix incompatibility introduced by gratuitous Emacs name change.
+;;
+(cond ((and (fboundp 'bookmark-name-from-record) (not (fboundp 'bookmark-name-from-full-record)))
+ (defalias 'bookmark-name-from-full-record 'bookmark-name-from-record))
+ ((and (fboundp 'bookmark-name-from-full-record) (not (fboundp 'bookmark-name-from-record)))
+ (defalias 'bookmark-name-from-record 'bookmark-name-from-full-record)))
+
+;; 2. The vanilla name of the first is misleading, as it returns only the cdr of the record.
+;; The second is for consistency.
+;;
+(defalias 'bmkp-bookmark-data-from-record 'bookmark-get-bookmark-record)
+(defalias 'bmkp-bookmark-name-from-record 'bookmark-name-from-full-record)
+
+
+(eval-when-compile
+ (or (condition-case nil
+ (load-library "bookmark+-mac") ; Use load-library to ensure latest .elc.
+ (error nil))
+ (require 'bookmark+-mac))) ; Require, so can load separately if not on `load-path'.
+;; bmkp-define-show-only-command, bmkp-define-sort-command, bmkp-menu-bar-make-toggle,
+;; bmkp-with-help-window, bmkp-with-output-to-plain-temp-buffer
+
+(put 'bmkp-with-output-to-plain-temp-buffer 'common-lisp-indent-function '(4 &body))
+
+
+;;; These functions are used in macro `bmkp-define-sort-command'. The first is used in the macro code
+;;; that produces the function code, so its definition is also in `bookmark+-mac.el'.
+;;;
+(defun bmkp-replace-regexp-in-string (regexp rep string &optional fixedcase literal subexp start)
+ "Replace all matches for REGEXP with REP in STRING and return STRING."
+ (if (fboundp 'replace-regexp-in-string) ; Emacs > 20.
+ (replace-regexp-in-string regexp rep string fixedcase literal subexp start)
+ (if (string-match regexp string) (replace-match rep nil nil string) string))) ; Emacs 20
+
+(defun bmkp-assoc-delete-all (key alist)
+ "Delete from ALIST all elements whose car is `equal' to KEY.
+Return the modified alist.
+Elements of ALIST that are not conses are ignored."
+ (while (and (consp (car alist)) (equal (car (car alist)) key)) (setq alist (cdr alist)))
+ (let ((tail alist)
+ tail-cdr)
+ (while (setq tail-cdr (cdr tail))
+ (if (and (consp (car tail-cdr)) (equal (car (car tail-cdr)) key))
+ (setcdr tail (cdr tail-cdr))
+ (setq tail tail-cdr))))
+ alist)
+
+
+;; (eval-when-compile (require 'bookmark+-1))
+
+;; bmkp-add-tags, bmkp-alpha-p, bmkp-bookmark-creation-cp,
+;; bmkp-bookmark-description, bmkp-bookmark-file-bookmark-p,
+;; bmkp-bookmark-last-access-cp, bmkp-bookmark-list-bookmark-p,
+;; bmkp-buffer-last-access-cp, bmkp-completing-read-buffer-name,
+;; bmkp-completing-read-file-name, bmkp-current-bookmark-file,
+;; bmkp-current-sort-order, bmkp-describe-bookmark,
+;; bmkp-describe-bookmark-internals, bmkp-desktop-bookmark-p,
+;; bmkp-edit-bookmark-name-and-location, bmkp-file-alpha-cp,
+;; bmkp-file-remote-p, bmkp-function-bookmark-p, bmkp-get-bookmark,
+;; bmkp-get-buffer-name, bmkp-get-tags, bmkp-gnus-bookmark-p,
+;; bmkp-gnus-cp, bmkp-handler-cp, bmkp-incremental-filter-delay,
+;; bmkp-image-bookmark-p, bmkp-info-bookmark-p,
+;; bmkp-info-node-name-cp, bmkp-info-position-cp,
+;; bmkp-isearch-bookmarks, bmkp-isearch-bookmarks-regexp, bmkp-jump-1,
+;; bmkp-last-bookmark-file, bmkp-last-specific-buffer,
+;; bmkp-last-specific-file, bmkp-latest-bookmark-alist,
+;; bmkp-local-file-bookmark-p, bmkp-local-file-type-cp,
+;; bmkp-local-file-accessed-more-recently-cp,
+;; bmkp-local-file-updated-more-recently-cp,
+;; bmkp-set-sequence-bookmark, bmkp-man-bookmark-p,
+;; bmkp-marked-bookmark-p, bmkp-marked-bookmarks-only, bmkp-marked-cp,
+;; bmkp-msg-about-sort-order, bmkp-non-file-filename,
+;; bmkp-read-tag-completing, bmkp-read-tags-completing,
+;; bmkp-refresh-menu-list, bmkp-region-bookmark-p,
+;; bmkp-remove-all-tags, bmkp-remove-if, bmkp-remove-tags,
+;; bmkp-repeat-command, bmkp-reverse-multi-sort-p,
+;; bmkp-reverse-sort-p, bmkp-root-or-sudo-logged-p, bmkp-same-file-p,
+;; bmkp-save-menu-list-state, bmkp-sequence-bookmark-p,
+;; bmkp-set-tag-value, bmkp-set-tag-value-for-bookmarks,
+;; bmkp-set-union, bmkp-snippet-alist-only, bmkp-snippet-bookmark-p,
+;; bmkp-some, bmkp-some-marked-p, bmkp-some-unmarked-p,
+;; bmkp-sort-omit, bmkp-sort-comparer, bmkp-sorted-alist,
+;; bmkp-su-or-sudo-regexp, bmkp-tag-name, bmkp-tags-list,
+;; bmkp-url-bookmark-p, bmkp-url-cp, bmkp-unmarked-bookmarks-only,
+;; bmkp-variable-list-bookmark-p, bmkp-visited-more-cp
+
+;; (eval-when-compile (require 'bookmark+-lit nil t))
+;; bmkp-get-lighting
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Quiet the byte-compiler
+(defvar bookmark-file-coding-system) ; In `bookmark.el' (Emacs 25.2+)
+(defvar bmkp-bmenu-buffer) ; In `bookmark+.el'
+(defvar bmkp-bmenu-highlight-menu) ; Defined in this file (conditionally).
+(defvar bmkp-copied-tags) ; In `bookmark+-1.el'.
+(defvar bmkp-count-multi-mods-as-one-flag) ; In `bookmark+-1.el'.
+(defvar bmkp-current-bookmark-file) ; In `bookmark+-1.el'.
+(defvar bmkp-edit-bookmark-orig-record) ; In `bookmark+-1.el'.
+(defvar bmkp-incremental-filter-delay) ; In `bookmark+-1.el'.
+(defvar bmkp-edit-bookmark-records-number) ; In `bookmark+-1.el'.
+(defvar bmkp-last-bookmark-file) ; In `bookmark+-1.el'.
+(defvar bmkp-last-specific-buffer) ; In `bookmark+-1.el'.
+(defvar bmkp-last-specific-file) ; In `bookmark+-1.el'.
+(defvar bmkp-latest-bookmark-alist) ; In `bookmark+-1.el'.
+(defvar bmkp-modified-bookmarks) ; In `bookmark+-1.el'.
+(defvar bmkp-non-file-filename) ; In `bookmark+-1.el'.
+(defvar bmkp-reverse-multi-sort-p) ; In `bookmark+-1.el'.
+(defvar bmkp-reverse-sort-p) ; In `bookmark+-1.el'.
+(defvar bmkp-sort-comparer) ; In `bookmark+-1.el'.
+(defvar bmkp-sorted-alist) ; In `bookmark+-1.el'.
+(defvar bmkp-sort-orders-alist) ; Here.
+(defvar bmkp-su-or-sudo-regexp) ; In `bookmark+-1.el'.
+(defvar bmkp-temporary-bookmarking-mode) ; In `bookmark+-1.el'.
+(defvar dired-re-mark) ; In `dired.el'.
+(defvar icicle-candidate-properties-alist) ; In `icicles-var.el'.
+(defvar minibuffer-prompt-properties) ; Emacs 22+.
+(defvar tramp-file-name-regexp) ; In `tramp.el'.
+
+
+;;(@* "Utility Functions")
+;;; Utility Functions ------------------------------------------------
+
+;; Same as `tap-string-match-p' in `thingatpt+.el' and `icicle-string-match-p' in `icicles-fn.el'.
+(if (fboundp 'string-match-p)
+ (defalias 'bmkp-string-match-p 'string-match-p) ; Emacs 23+
+ (defun bmkp-string-match-p (regexp string &optional start)
+ "Like `string-match', but this saves and restores the match data."
+ (save-match-data (string-match regexp string start))))
+
+;; Same as `tap-looking-at-p' in `thingatpt+.el' and `icicle-looking-at-p' in `icicles-mcmd.el'.
+;; Do not `defalias' to Emacs `looking-at-p' because that is a `defsubst'.
+(defun bmkp-looking-at-p (regexp)
+ "Like `looking-at', but this saves and restores the match data."
+ (save-match-data (looking-at regexp)))
+
+;; Same as `icicle-remap' in `icicles-opt.el'. Not used yet.
+(defun bmkp-remap (old new map &optional oldmap)
+ "Bind command NEW in MAP to all keys currently bound to OLD.
+If command remapping is available, use that. Otherwise, bind NEW to
+whatever OLD is bound to in MAP, or in OLDMAP, if provided."
+ (if (fboundp 'command-remapping)
+ (define-key map (vector 'remap old) new) ; Ignore OLDMAP for Emacs 22.
+ (substitute-key-definition old new map oldmap)))
+
+;; This is also in `bookmark+-lit.el', since it is loaded first but is optional.
+;;
+(if (fboundp 'pop-to-buffer-same-window)
+ (defalias 'bmkp--pop-to-buffer-same-window 'pop-to-buffer-same-window)
+ (defalias 'bmkp--pop-to-buffer-same-window 'switch-to-buffer))
+
+;;(@* "Faces (Customizable)")
+;;; Faces (Customizable) ---------------------------------------------
+
+(defface bmkp->-mark '((((background dark)) (:foreground "Yellow"))
+ (t (:foreground "Blue")))
+ ;; (:foreground "Magenta2" :box (:line-width 1 :style pressed-button))))
+ "*Face used for a `>' mark in the bookmark list."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-a-mark '((((background dark)) (:background "SaddleBrown"))
+ (t (:background "SkyBlue")))
+ "*Face used for an annotation indicator (`a') in the bookmark list."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-bad-bookmark '((t (:foreground "Red" :background "Chartreuse1")))
+ "*Face used for a bookmark that seems to be bad: e.g., nonexistent file."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-bookmark-file
+ '((((background dark))
+ (:foreground "#00005A5AFFFF" :background "#FFFF9B9BFFFF")) ; ~ blue, ~ pink
+ (t (:foreground "Orange" :background "DarkGreen")))
+ "*Face used for a bookmark-file bookmark."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-bookmark-list
+ '((((background dark)) (:foreground "#7474FFFFFFFF" :background "DimGray")) ; ~ cyan
+ (t (:foreground "DarkRed" :background "LightGray")))
+ "*Face used for a bookmark-list bookmark."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-buffer
+ '((((background dark)) (:foreground "#FFFF9B9BFFFF")) ; ~ pink
+ (t (:foreground "DarkGreen")))
+ "*Face used for a bookmarked existing buffer not associated with a file."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-D-mark '((t (:foreground "Yellow" :background "Red")))
+ "*Face used for a deletion mark (`D') in the bookmark list."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-desktop
+ '((((background dark)) (:foreground "Orange" :background "DarkSlateBlue"))
+ (t (:foreground "DarkBlue" :background "PaleGoldenrod")))
+ "*Face used for a bookmarked desktop."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-file-handler
+ '((((background dark)) (:background "#FFFF78CB48E1")) ; ~ dark brown
+ (t (:background "LightBlue")))
+ "*Face used for a bookmark that has a `file-handler' attribute."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-function
+ '((((background dark)) (:foreground "#0000EBEB6C6C")) ; ~ green
+ (t (:foreground "DeepPink1")))
+ "*Face used for a function bookmark: a bookmark that invokes a function."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-gnus
+ '((((background dark)) (:foreground "Gold"))
+ (t (:foreground "DarkBlue")))
+ "*Face used for a Gnus bookmark."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-info
+ '((((background dark)) (:foreground "#7474FFFFFFFF")) ; ~ light cyan
+ (t (:foreground "DarkRed")))
+ "*Face used for a bookmarked Info node."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-local-directory
+ '((((background dark))
+ (:foreground "Pink" :background "DarkBlue"))
+ (t (:foreground "DarkBlue" :background "HoneyDew2")))
+ "*Face used for a bookmarked local directory."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-local-file-without-region
+ '((((background dark)) (:foreground "White"))
+ (t (:foreground "Black")))
+ "*Face used for a bookmarked local file (without a region)."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-local-file-with-region
+ '((((background dark)) (:foreground "Yellow"))
+ (t (:foreground "Blue")))
+ "*Face used for a region bookmark in a local file."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-man
+ '((((background dark)) (:foreground "Orchid"))
+ (t (:foreground "Orange4")))
+ "*Face used for a `man' page bookmark."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-*-mark '((t (:foreground "Red" :background "Yellow")))
+ "*Face used for a modification mark (`*') in the bookmark list."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-no-jump
+ '((t (:foreground "gray50")))
+ "*Face used for a bookmark you cannot jump to from `*Bookmark List*'."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-no-local
+ '((t (:background "orange")))
+ "*Face used for a local file bookmark whose target file does not exist."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-non-file
+ '((t (:foreground "MediumSeaGreen")))
+ "*Face used for a bookmark not associated with an existing buffer."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-remote-file
+ '((((background dark)) (:foreground "#6B6BFFFF2C2C")) ; ~ green
+ (t (:foreground "DarkViolet")))
+ "*Face used for a bookmarked tramp remote file (/ssh:)."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-sequence
+ '((((background dark)) (:foreground "DeepSkyBlue"))
+ (t (:foreground "DarkOrange2")))
+ "*Face used for a sequence bookmark: one composed of other bookmarks."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-snippet
+ (if (> emacs-major-version 21)
+ '((t (:inherit region)))
+ '((t (:background "MediumAquamarine"))))
+ "*Face used for a bookmarked snippet."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-su-or-sudo '((t (:foreground "Red")))
+ "*Face used for a bookmarked tramp file (/su: or /sudo:)."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-t-mark '((((background dark)) (:foreground "Magenta"))
+ (t (:foreground "#000093F402A2"))) ; a medium green
+ "*Face used for a tags mark (`t') in the bookmark list."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-url
+ '((((background dark)) (:foreground "#7474FFFF7474")) ; ~ green
+ (t (:foreground "DarkMagenta")))
+ "*Face used for a bookmarked URL."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-variable-list
+ '((((background dark)) (:foreground "#FFFF8D947477")) ; ~ salmon
+ (t (:foreground "#0000726B8B8B"))) ; ~dark cyan
+ "*Face used for a bookmarked list of variables."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-X-mark '((t (:foreground "Red")))
+ "*Face used for a temporary-bookmark indicator (`X') in the bookmark list."
+ :group 'bookmark-plus :group 'faces)
+
+;; $$$$$$ Not used now - using `bmkp-url' instead.
+;; (defface bmkp-w3m
+;; '((((background dark)) (:foreground "yellow"))
+;; (t (:foreground "DarkMagenta")))
+;; "*Face used for a bookmarked w3m url."
+;; :group 'bookmark-plus :group 'faces)
+
+;; Instead of vanilla `bookmark-menu-heading' (defined in Emacs 22+), to use a better default.
+(defface bmkp-heading '((((background dark)) (:foreground "Yellow"))
+ (t (:foreground "Blue")))
+ "*Face used to highlight the headings in various Bookmark+ buffers."
+ :group 'bookmark-plus :version "22.1" :group 'faces)
+
+;;(@* "User Options (Customizable)")
+;;; User Options (Customizable) --------------------------------------
+
+;;;###autoload (autoload 'bmkp-bmenu-omitted-bookmarks "bookmark+")
+(defcustom bmkp-bmenu-omitted-bookmarks ()
+ "*List of names of omitted bookmarks.
+They are generally not available for display in the bookmark list.
+You can, however, use \\<bookmark-bmenu-mode-map>\
+`\\[bmkp-bmenu-show-only-omitted-bookmarks]' to see them.
+You can then mark some of them and use `\\[bmkp-bmenu-omit/unomit-marked]'
+ to make those that are marked available again for the bookmark list."
+ ;; $$$$$$ TODO: Create a customize :type `bookmark-name'
+ ;; and provide completion for filling out the field.
+ :type '(repeat (string :tag "Bookmark name")) :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-bmenu-commands-file "bookmark+")
+(defcustom bmkp-bmenu-commands-file (convert-standard-filename "~/.emacs-bmk-bmenu-commands.el")
+ "*File for saving user-defined bookmark-list commands.
+This must be an absolute file name (possibly containing `~') or nil
+\(it is not expanded).
+
+You can use `\\[bmkp-list-defuns-in-commands-file]' to list the
+commands defined in the file and how many times each is defined.
+
+NOTE: Each time you define a command using \\<bookmark-bmenu-mode-map>\
+`\\[bmkp-bmenu-define-command]', `\\[bmkp-bmenu-define-full-snapshot-command]', \
+`\\[bmkp-bmenu-define-jump-marked-command], or `\\[bmkp-define-tags-sort-command]',
+it is saved in the file. The new definition is simply appended to the
+file - old definitions of the same command are not overwritten. So
+you might want to clean up the file occasionally, to remove any old,
+unused definitions. This is especially advisable if you used \
+`\\[bmkp-bmenu-define-full-snapshot-command]',
+because such command definitions can be very large."
+ :type '(file :tag "File for saving menu-list state") :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-bmenu-state-file "bookmark+")
+(defcustom bmkp-bmenu-state-file (convert-standard-filename "~/.emacs-bmk-bmenu-state.el")
+ "*File for saving `*Bookmark List*' state when you quit bookmark list.
+This must be an absolute file name (possibly containing `~') or nil
+\(it is not expanded).
+
+The state is also saved when you quit Emacs, even if you don't quit
+the bookmark list first (using \\<bookmark-bmenu-mode-map>`\\[bmkp-bmenu-quit]').
+
+Set this to nil if you do not want to restore the bookmark list as it
+was the last time you used it."
+ :type '(choice
+ (const :tag "Do not save and restore menu-list state" nil)
+ (file :tag "File for saving menu-list state"))
+ :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-bmenu-image-bookmark-icon-file "bookmark+")
+(defcustom bmkp-bmenu-image-bookmark-icon-file
+ (and (fboundp 'display-images-p) (display-images-p)
+ (let ((bmk-img (convert-standard-filename "~/.emacs-bmk-bmenu-image-file-icon.png"))
+ (emacs-img (convert-standard-filename (concat data-directory "images/gnus/exit-gnus.xpm"))))
+ (or (and (file-readable-p bmk-img) bmk-img)
+ (and (file-readable-p emacs-img) emacs-img))))
+ "*Iconic image file to show next to image-file bookmarks.
+If nil, show no image. Otherwise, this is an absolute file name,
+possibly containing `~', (the value is not expanded).
+
+Use any image file that Emacs can display, but you probably want to
+use a small, iconic image - say 16x16 pixels.
+
+The default image, which you are sure to have in any Emacs version
+that supports images, is 24x24 pixels. That wastes vertical space, so
+you probably want to use something smaller.
+
+If you don't have another image that you prefer, try this one (16x16):
+https://www.emacswiki.org/emacs/BookmarkPlusImageFileDefaultIcon"
+ :type '(choice
+ (file :tag "Use iconic image file")
+ (const :tag "Show no image"))
+ :group 'bookmark-plus)
+
+;; This is a general option. It is in this file because it is used mainly by the bmenu code.
+(when (> emacs-major-version 20)
+ (defcustom bmkp-sort-orders-alist ()
+ "*Alist of all available sort functions.
+This is a pseudo option - you probably do NOT want to customize this.
+Instead:
+
+ * To add a new sort function to this list, use macro
+ `bmkp-define-sort-command'. It defines a new sort function
+ and automatically adds it to this list.
+
+ * To have fewer sort orders available for cycling by \\<bookmark-bmenu-mode-map>\
+`\\[bmkp-bmenu-change-sort-order-repeat]'...,
+ customize option `bmkp-sort-orders-for-cycling-alist'.
+
+Each alist element has the form (SORT-ORDER . COMPARER):
+
+ SORT-ORDER is a short string or symbol describing the sort order.
+ Examples: \"by last access time\", \"by bookmark name\".
+
+ COMPARER compares two bookmarks. It must be acceptable as a value of
+ `bmkp-sort-comparer'."
+ :type '(alist
+ :key-type (choice :tag "Sort order" string symbol)
+ :value-type (choice
+ (const :tag "None (do not sort)" nil)
+ (function :tag "Sorting Predicate")
+ (list :tag "Sorting Multi-Predicate"
+ (repeat (function :tag "Component Predicate"))
+ (choice
+ (const :tag "None" nil)
+ (function :tag "Final Predicate")))))
+ :group 'bookmark-plus))
+
+(unless (> emacs-major-version 20) ; Emacs 20: custom type `alist' doesn't exist.
+ (defcustom bmkp-sort-orders-alist ()
+ "*Alist of all available sort functions.
+This is a pseudo option - you probably do NOT want to customize this.
+Instead:
+
+ * To add a new sort function to this list, use macro
+ `bmkp-define-sort-command'. It defines a new sort function
+ and automatically adds it to this list.
+
+ * To have fewer sort orders available for cycling by \\<bookmark-bmenu-mode-map>\
+`\\[bmkp-bmenu-change-sort-order-repeat]'...,
+ customize option `bmkp-sort-orders-for-cycling-alist'.
+
+Each alist element has the form (SORT-ORDER . COMPARER):
+
+ SORT-ORDER is a short string or symbol describing the sort order.
+ Examples: \"by last access time\", \"by bookmark name\".
+
+ COMPARER compares two bookmarks. It must be acceptable as a value of
+ `bmkp-sort-comparer'."
+ :type '(repeat
+ (cons
+ (choice :tag "Sort order" string symbol)
+ (choice
+ (const :tag "None (do not sort)" nil)
+ (function :tag "Sorting Predicate")
+ (list :tag "Sorting Multi-Predicate"
+ (repeat (function :tag "Component Predicate"))
+ (choice
+ (const :tag "None" nil)
+ (function :tag "Final Predicate"))))))
+ :group 'bookmark-plus))
+
+(defcustom bmkp-propertize-bookmark-names-flag (> emacs-major-version 20)
+ "*Non-nil means to propertize bookmark names to hold full bookmark data.
+This means that you can effectively have more than one bookmark with
+the same name.
+
+Emacs 20 users: If you need to use your bookmarks with Emacs 20 then
+set this to nil. In particular, if your bookmark file was written
+with this as non-nil, then it contains propertized strings which are
+unreadable by Emacs 20. To convert the file to be usable with Emacs
+20 you must, in Emacs 21 or later, set this to nil and then do `M-x
+bookmark-save'."
+ :type 'boolean :group 'bookmark-plus)
+
+;;(@* "Internal Variables")
+;;; Internal Variables -----------------------------------------------
+
+(defconst bmkp-bmenu-header-lines 5
+ "Number of lines used for the `*Bookmark List*' header.")
+
+(defconst bmkp-bmenu-marks-width 4
+ "Number of columns (chars) used for the `*Bookmark List*' marks columns.
+Bookmark names thus begin in this column number (since zero-based).")
+
+
+(defvar bmkp-bmenu-before-hide-marked-alist ()
+ "Copy of `bookmark-alist' made before hiding marked bookmarks.")
+
+(defvar bmkp-bmenu-before-hide-unmarked-alist ()
+ "Copy of `bookmark-alist' made before hiding unmarked bookmarks.")
+
+(defvar bmkp-bmenu-define-command-history ()
+ "History of names of commands you have defined for `*Bookmark List*'.")
+
+(defvar bmkp-bmenu-filter-function nil "Latest filtering function for `*Bookmark List*' display.")
+
+(defvar bmkp-bmenu-filter-pattern "" "Regexp for incremental filtering.")
+
+(defvar bmkp-bmenu-filter-timer nil "Timer used for incremental filtering.")
+
+(defvar bmkp-bmenu-first-time-p t
+ "Non-nil means bookmark list has not yet been shown after quitting it.
+Quitting the list or the Emacs session resets this to t.
+The first time the list is displayed, it is set to nil.")
+
+(defvar bmkp-bmenu-marked-bookmarks ()
+ "Names of the marked bookmarks.
+This includes possibly omitted bookmarks, that is, bookmarks listed in
+`bmkp-bmenu-omitted-bookmarks'.")
+
+(defvar bmkp-bmenu-title "" "Latest title for `*Bookmark List*' display.")
+
+(defvar bmkp-flagged-bookmarks ()
+ "Alist of bookmarks that are flagged for deletion in `*Bookmark List*'.")
+
+;; This is a general variable. It is in this file because it is used only in the bmenu code.
+(defvar bmkp-last-bmenu-bookmark nil "The name of the last bookmark current in the bookmark list.")
+
+;;(@* "Compatibility Code for Older Emacs Versions")
+;;; Compatibility Code for Older Emacs Versions ----------------------
+
+(when (or (< emacs-major-version 23) (and (= emacs-major-version 23) (= emacs-minor-version 1)))
+ (defmacro with-buffer-modified-unmodified (&rest body)
+ "Save and restore `buffer-modified-p' state around BODY."
+ (let ((was-modified (make-symbol "was-modified")))
+ `(let ((,was-modified (buffer-modified-p)))
+ (unwind-protect (progn ,@body)
+ (set-buffer-modified-p ,was-modified))))))
+
+(when (< emacs-major-version 22)
+ (defun bookmark-bmenu-relocate ()
+ "Change the file path of the bookmark on the current line,
+prompting with completion for the new path."
+ (interactive)
+ (let ((bmk (bookmark-bmenu-bookmark))
+ (thispoint (point)))
+ (when bmk (bookmark-relocate bmk))
+ (goto-char thispoint))))
+
+;;(@* "Menu List Replacements (`bookmark-bmenu-*')")
+;;; Menu List Replacements (`bookmark-bmenu-*') ----------------------
+
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Return t. Value doesn't mean anything (didn't anyway), but must be non-nil for vanilla Emacs.
+;; 2. Do not count lines. Just make sure we're on a bookmark line.
+;;
+(defalias 'bookmark-bmenu-check-position 'bookmark-bmenu-ensure-position)
+(defun bookmark-bmenu-ensure-position ()
+ "Move to the beginning of the nearest bookmark line."
+ (beginning-of-line)
+ (unless (bookmark-bmenu-bookmark)
+ (if (and (bolp) (eobp))
+ (beginning-of-line 0)
+ (goto-char (point-min))
+ (forward-line bmkp-bmenu-header-lines)))
+ t) ; Older vanilla bookmark code depends on non-nil value.
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Add bookmark to `bmkp-bmenu-marked-bookmarks'. Delete it from `bmkp-flagged-bookmarks'.
+;; 2. Don't call `bookmark-bmenu-ensure-position' again at end.
+;; 3. Raise error if not in `*Bookmark List*'.
+;; 4. Narrower scope for `with-buffer-modified-unmodified' and `let'.
+;; 5. If current sort is `s >' (marked first or last), and it was unmarked before, then re-sort.
+;; 6. Added optional arg NO-RE-SORT-P to inhibit #5.
+;; 7. Added optional arg MSG-P.
+;; 8. Call `bmkp-bmenu-mode-line'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-mark "bookmark+")
+(defun bookmark-bmenu-mark (&optional no-re-sort-p msg-p) ; Bound to `m' in bookmark list
+ "Mark the bookmark on this line, using mark `>'.
+Add its name to `bmkp-bmenu-marked-bookmarks', after propertizing it
+with the full bookmark as `bmkp-full-record'.
+
+If the bookmark was unmarked before, and if the sort order is marked
+first or last (`s >'), then re-sort.
+
+Non-interactively:
+* Non-nil optional arg NO-RE-SORT-P inhibits re-sorting.
+* Non-nil optional arg MSG-P means display a status message."
+ (interactive (list nil 'MSG-P))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (beginning-of-line)
+ (with-buffer-modified-unmodified
+ (let ((inhibit-read-only t))
+ (delete-char 1) (insert ?>) (put-text-property (1- (point)) (point) 'face 'bmkp->-mark)))
+ (let* ((bname (bookmark-bmenu-bookmark))
+ (bmk (bmkp-bookmark-record-from-name bname))
+ (was-unmarked-p nil))
+ ;; Put full bookmark on BNAME as property `bmkp-full-record'.
+ (put-text-property 0 (length bname) 'bmkp-full-record bmk bname)
+ ;; This is the same as `add-to-list' with `eq' (not available for Emacs 20-21).
+ (unless (memq bname bmkp-bmenu-marked-bookmarks)
+ (setq bmkp-bmenu-marked-bookmarks (cons bname bmkp-bmenu-marked-bookmarks)
+ was-unmarked-p t))
+ (setq bmkp-flagged-bookmarks (delq bmk bmkp-flagged-bookmarks))
+ (unless no-re-sort-p
+ ;; If it was unmarked but now is marked, and if sort order is `s >', then re-sort.
+ (when (and was-unmarked-p (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list (not msg-p))
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk))))))
+ (forward-line 1)
+ (when (fboundp 'bmkp-bmenu-mode-line) (bmkp-bmenu-mode-line)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Remove bookmark from `bmkp-bmenu-marked-bookmarks' and `bmkp-flagged-bookmarks'.
+;; 2. Use `bmkp-delete-bookmark-name-from-list', not `delete'.
+;; 3. Don't call `bookmark-bmenu-ensure-position' again at end.
+;; 4. Raise error if not in `*Bookmark List*'.
+;; 5. Narrower scope for `with-buffer-modified-unmodified' and `let'.
+;; 6. If current sort is `s >' (marked first or last), and it was marked before, then re-sort.
+;; 7. Added optional arg NO-RE-SORT-P to inhibit #6.
+;; 8. Added optional arg MSG-P.
+;; 9. Call `bmkp-bmenu-mode-line'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-unmark "bookmark+")
+(defun bookmark-bmenu-unmark (&optional backup no-re-sort-p msg-p) ; Bound to `u' in bookmark list
+ "Unmark the bookmark on this line, then move down to the next.
+With a prefix argument, move up instead.
+
+If the bookmark was marked before, and if the sort order is marked
+first or last (`s >'), then re-sort.
+
+Non-interactively:
+* Non-nil optional arg BACKUP (prefix arg) means move up.
+* Non-nil optional arg NO-RE-SORT-P inhibits re-sorting.
+* Non-nil optional arg MSG-P means display a status message."
+ (interactive (list current-prefix-arg nil 'MSG-P))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (beginning-of-line)
+ (with-buffer-modified-unmodified
+ (let ((inhibit-read-only t))
+ (delete-char 1) (insert " ")))
+ (let ((was-marked-p (memq (bookmark-bmenu-bookmark) bmkp-bmenu-marked-bookmarks)))
+ (setq bmkp-bmenu-marked-bookmarks (bmkp-delete-bookmark-name-from-list
+ (bookmark-bmenu-bookmark) bmkp-bmenu-marked-bookmarks)
+ bmkp-flagged-bookmarks (delq (bmkp-bookmark-record-from-name (bookmark-bmenu-bookmark))
+ bmkp-flagged-bookmarks))
+ (unless no-re-sort-p
+ ;; If it was marked but now is unmarked, and if sort order is `s >', then re-sort.
+ (when (and was-marked-p (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list (not msg-p))
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk))))))
+ (forward-line (if backup -1 1))
+ (when (fboundp 'bmkp-bmenu-mode-line) (bmkp-bmenu-mode-line)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Do not use `bookmark-bmenu-ensure-position' as a test - it always returns non-nil anyway.
+;; And don't call it again the end.
+;; 2. Use `bmkp-delete-bookmark-name-from-list', not `delete'.
+;; 3. Use face `bmkp-D-mark' on the `D' flag.
+;; 4. Raise error if not in buffer `*Bookmark List*'.
+;; 5. Remove bookmark from `bmkp-bmenu-marked-bookmarks'. Add it to `bmkp-flagged-bookmarks'.
+;; 6. Call `bmkp-bmenu-mode-line'.
+;;
+;;;###autoload (autoload 'bmkp-bmenu-flag-for-deletion "bookmark+")
+(defalias 'bmkp-bmenu-flag-for-deletion 'bookmark-bmenu-delete) ; A better name.
+;;;###autoload (autoload 'bookmark-bmenu-delete "bookmark+")
+(defun bookmark-bmenu-delete () ; Bound to `d', `k' in bookmark list
+ "Flag this bookmark for deletion, using mark `D'.
+Use `\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]' to carry out \
+the deletions."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (beginning-of-line)
+ (bookmark-bmenu-ensure-position)
+ (with-buffer-modified-unmodified
+ (let ((inhibit-read-only t))
+ (delete-char 1) (insert ?D) (put-text-property (1- (point)) (point) 'face 'bmkp-D-mark)))
+ (when (bookmark-bmenu-bookmark) ; Should never be nil, but just to be safe.
+ (setq bmkp-bmenu-marked-bookmarks (bmkp-delete-bookmark-name-from-list
+ (bookmark-bmenu-bookmark) bmkp-bmenu-marked-bookmarks))
+ ;; This is the same as `add-to-list' with `eq' (not available for Emacs 20-21).
+ (let ((bmk (bmkp-bookmark-record-from-name (bookmark-bmenu-bookmark))))
+ (unless (memq bmk bmkp-flagged-bookmarks)
+ (setq bmkp-flagged-bookmarks (cons bmk bmkp-flagged-bookmarks)))))
+ (forward-line 1)
+ (when (fboundp 'bmkp-bmenu-mode-line) (bmkp-bmenu-mode-line)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Do not move forward another line at end. Leave point above flagged bookmark.
+;;
+;;;###autoload (autoload 'bmkp-bmenu-flag-for-deletion-backwards "bookmark+")
+(defalias 'bmkp-bmenu-flag-for-deletion-backwards 'bookmark-bmenu-delete-backwards) ; A better name.
+;;;###autoload (autoload 'bookmark-bmenu-delete-backwards "bookmark+")
+(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)
+ (bookmark-bmenu-delete)
+ (forward-line -2)
+ (bookmark-bmenu-ensure-position))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg NO-MSG-P.
+;; 2. Rebuild the menu list using the last filtered alist in use, `bmkp-latest-bookmark-alist'.
+;; 3. Update the menu-list title.
+;;
+(defun bookmark-bmenu-surreptitiously-rebuild-list (&optional no-msg-p)
+ "Rebuild the bookmark list, if it exists.
+Non-nil optional arg NO-MSG-P means do not show progress messages."
+ (when (get-buffer bmkp-bmenu-buffer)
+ (unless no-msg-p (message "Updating bookmark-list display..."))
+ (save-excursion (save-window-excursion (let ((bookmark-alist bmkp-latest-bookmark-alist))
+ (bookmark-bmenu-list 'filteredp))))
+ (unless no-msg-p (message "Updating bookmark-list display...done"))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added arg FILTEREDP.
+;; 2. Handles also region bookmarks and buffer (non-file) bookmarks.
+;; 3. Uses `pop-to-buffer', not `switch-to-buffer', so we respect `special-display-*'
+;; (but keep `one-window-p' if that's the case).
+;; 4. If option `bmkp-bmenu-state-file' is non-nil, then the first time since the last quit
+;; (or the last Emacs session) restores the last menu-list state.
+;; 5. If option `bmkp-bmenu-commands-file' is non-nil, then read that file, which contains
+;; user-defined `*Bookmark List*' commands.
+;; 6. Many differences in the display itself - see the doc.
+;;
+;;;###autoload (autoload 'list-bookmarks "bookmark+")
+(defalias 'list-bookmarks 'bookmark-bmenu-list)
+;;;###autoload (autoload 'bookmark-bmenu-list "bookmark+")
+(defun bookmark-bmenu-list (&optional filteredp msg-p) ; Bound to `C-x x e', `C-x r l'
+ "Display a list of existing bookmarks, in buffer `*Bookmark List*'.
+The leftmost column of a bookmark entry shows `D' if the bookmark is
+ flagged for deletion, or `>' if it is marked normally.
+The second column shows `t' if the bookmark has tags.
+The third column shows `a' if the bookmark has an annotation.
+
+The following faces are used for the list entries.
+Use `customize-face' if you want to change the appearance.
+
+ `bmkp-bad-bookmark', `bmkp-bookmark-file', `bmkp-bookmark-list',
+ `bmkp-buffer', `bmkp-desktop', `bmkp-file-handler', `bmkp-function',
+ `bmkp-gnus', `bmkp-info', `bmkp-local-directory',
+ `bmkp-local-file-without-region', `bmkp-local-file-with-region',
+ `bmkp-man', `bmkp-no-jump', `bmkp-no-local', `bmkp-non-file',
+ `bmkp-remote-file', `bmkp-sequence', `bmkp-snippet',
+ `bmkp-su-or-sudo', `bmkp-url', `bmkp-variable-list'
+
+If option `bmkp-bmenu-state-file' is non-nil then the state of the
+displayed bookmark-list is saved when you quit it, and it is restored
+when you next use this command. That saved state is not restored,
+however, if it represents a different file from the current bookmark
+file.
+
+If you call this interactively when buffer `*Bookmark List*' exists,
+that buffer is refreshed to show all current bookmarks, and any
+markings are removed. If you instead want to show the buffer in its
+latest state then just do that: use `C-x b' or similar. If you want
+to refresh the displayed buffer, to show the latest state, reflecting
+any additions, deletions, renamings, and so on, use \\<bookmark-bmenu-mode-map>\
+`\\[bmkp-bmenu-refresh-menu-list]'.
+
+
+Non-interactively:
+
+ - Non-nil optional argument FILTEREDP means the bookmark list has
+ been filtered, which means:
+
+ * Use `bmkp-bmenu-title' not the default menu-list title.
+ * Do not reset `bmkp-latest-bookmark-alist' to `bookmark-alist'.
+
+ - Non-nil optional arg MSG-P means display progress messages."
+ (interactive "i\np")
+ (bookmark-maybe-load-default-file)
+ (when msg-p (message "Gathering bookmarks to display..."))
+ (when (and bmkp-bmenu-first-time-p bmkp-bmenu-commands-file
+ (file-readable-p bmkp-bmenu-commands-file))
+ (when (file-directory-p bmkp-bmenu-commands-file)
+ (error "`%s' is a directory, not a file" bmkp-bmenu-commands-file))
+ (with-current-buffer (let ((enable-local-variables ())
+ (emacs-lisp-mode-hook nil))
+ (find-file-noselect bmkp-bmenu-commands-file))
+ (goto-char (point-min))
+ (while (not (eobp)) (condition-case nil (eval (read (current-buffer))) (error nil)))
+ (kill-buffer (current-buffer))))
+ (cond ((and bmkp-bmenu-first-time-p bmkp-bmenu-state-file ; Restore from state file.
+ (file-readable-p bmkp-bmenu-state-file))
+ (when (file-directory-p bmkp-bmenu-state-file)
+ (error "`%s' is a directory, not a file" bmkp-bmenu-state-file))
+ (let ((state ()))
+ (with-current-buffer (let ((enable-local-variables nil)
+ (emacs-lisp-mode-hook nil))
+ (find-file-noselect bmkp-bmenu-state-file))
+ (goto-char (point-min))
+ (setq state (condition-case nil (read (current-buffer)) (error nil)))
+ (kill-buffer (current-buffer)))
+ (let ((last-bookmark-file-from-state (cdr (assq 'last-bookmark-file state))))
+ (when (and (consp state)
+ ;; If bookmark file has changed, then do not use state saved from other file.
+ (or (not last-bookmark-file-from-state)
+ (bmkp-same-file-p last-bookmark-file-from-state
+ bmkp-current-bookmark-file)))
+ (setq bmkp-sort-comparer (cdr (assq 'last-sort-comparer state))
+ bmkp-reverse-sort-p (cdr (assq 'last-reverse-sort-p state))
+ bmkp-reverse-multi-sort-p (cdr (assq 'last-reverse-multi-sort-p state))
+ bmkp-latest-bookmark-alist (cdr (assq 'last-latest-bookmark-alist state))
+ bmkp-bmenu-omitted-bookmarks (cdr (assq 'last-bmenu-omitted-bookmarks state))
+ bmkp-bmenu-marked-bookmarks (cdr (assq 'last-bmenu-marked-bookmarks state))
+ bmkp-bmenu-filter-function (cdr (assq 'last-bmenu-filter-function state))
+ bmkp-bmenu-filter-pattern (or (cdr (assq 'last-bmenu-filter-pattern state))
+ "")
+ bmkp-bmenu-title (cdr (assq 'last-bmenu-title state))
+ bmkp-last-bmenu-bookmark (cdr (assq 'last-bmenu-bookmark state))
+ bmkp-last-specific-buffer (cdr (assq 'last-specific-buffer state))
+ bmkp-last-specific-file (cdr (assq 'last-specific-file state))
+ bookmark-bmenu-toggle-filenames (cdr (assq 'last-bmenu-toggle-filenames state))
+ bmkp-last-bookmark-file (or (cdr (assq 'last-previous-bookmark-file state))
+ bmkp-current-bookmark-file)
+ bmkp-current-bookmark-file last-bookmark-file-from-state
+ bmkp-bmenu-before-hide-marked-alist
+ (cdr (assq 'last-bmenu-before-hide-marked-alist state))
+ bmkp-bmenu-before-hide-unmarked-alist
+ (cdr (assq 'last-bmenu-before-hide-unmarked-alist state))))))
+ (setq bmkp-bmenu-first-time-p nil)
+ (let ((bookmark-alist (bmkp-refresh-latest-bookmark-list))) ; This sets *-latest-* also.
+ (bmkp-bmenu-list-1 'filteredp nil msg-p))
+ ;; Propertize bookmark names if not already propertized (lists saved with Emacs 20 or
+ ;; not `bmkp-propertize-bookmark-names-flag'). Check only the first, to guess propertized.
+ (when (and (consp bmkp-bmenu-marked-bookmarks)
+ (not (get-text-property 0 'bmkp-full-record (car bmkp-bmenu-marked-bookmarks))))
+ (setq bmkp-bmenu-marked-bookmarks
+ (condition-case nil
+ (mapcar (lambda (bname)
+ (if (get-text-property 0 'bmkp-full-record bname)
+ bname
+ (put-text-property 0 (length bname) 'bmkp-full-record
+ (bmkp-bookmark-record-from-name bname) bname)
+ bname))
+ bmkp-bmenu-marked-bookmarks)
+ (error ())))) ; Reset to () if any name is not a current bookmark.
+ (when (and (consp bmkp-bmenu-omitted-bookmarks)
+ (not (get-text-property 0 'bmkp-full-record (car bmkp-bmenu-omitted-bookmarks))))
+ (setq bmkp-bmenu-omitted-bookmarks
+ (condition-case nil
+ (mapcar (lambda (bname)
+ (if (get-text-property 0 'bmkp-full-record bname)
+ bname
+ (put-text-property 0 (length bname) 'bmkp-full-record
+ (bmkp-bookmark-record-from-name bname) bname)
+ bname))
+ bmkp-bmenu-omitted-bookmarks)
+ (error ())))) ; Reset to () if any name is not a current bookmark.
+ (when bmkp-last-bmenu-bookmark
+ (with-current-buffer (get-buffer bmkp-bmenu-buffer)
+ (bmkp-bmenu-goto-bookmark-named bmkp-last-bmenu-bookmark))))
+ (t
+ (setq bmkp-bmenu-first-time-p nil)
+ (bmkp-bmenu-list-1 filteredp (or msg-p (not (get-buffer bmkp-bmenu-buffer))) msg-p))))
+
+(defun bmkp-bmenu-list-1 (filteredp reset-p interactivep)
+ "Helper for `bookmark-bmenu-list'.
+See `bookmark-bmenu-list' for the description of FILTEREDP.
+Reset `bmkp-modified-bookmarks' and `bmkp-flagged-bookmarks'.
+Non-nil RESET-P means reset `bmkp-bmenu-marked-bookmarks' also.
+Non-nil INTERACTIVEP means `bookmark-bmenu-list' was called
+ interactively, so pop to bookmark list and communicate sort order."
+ (setq bmkp-modified-bookmarks ()
+ bmkp-flagged-bookmarks ())
+ (when reset-p (setq bmkp-bmenu-marked-bookmarks ()))
+;; $$$$$$ Took out 2015/01/22. (unless filteredp (setq bmkp-latest-bookmark-alist bookmark-alist))
+ (if interactivep
+ (let ((one-win-p (one-window-p)))
+ (pop-to-buffer (get-buffer-create bmkp-bmenu-buffer))
+ (when one-win-p (delete-other-windows)))
+ (set-buffer (get-buffer-create bmkp-bmenu-buffer)))
+ (let* ((inhibit-read-only t)
+ (title (if (and filteredp bmkp-bmenu-title (not (equal "" bmkp-bmenu-title)))
+ bmkp-bmenu-title
+ "All Bookmarks"))
+ (show-image-file-icon-p (and (fboundp 'display-images-p) (display-images-p)
+ bmkp-bmenu-image-bookmark-icon-file
+ (file-readable-p bmkp-bmenu-image-bookmark-icon-file))))
+ (erase-buffer)
+ (when (fboundp 'remove-images) (remove-images (point-min) (point-max)))
+ (insert (format "%s\n%s\n" title (make-string (length title) ?-)))
+ (add-text-properties (point-min) (point) (bmkp-face-prop 'bmkp-heading))
+ (goto-char (point-min))
+ (insert (format "Bookmark file:\n%s\n\n" bmkp-current-bookmark-file))
+ (forward-line bmkp-bmenu-header-lines)
+ (let ((max-width 0)
+ name markedp flaggedp tags annotation temporaryp start)
+ (setq bmkp-sorted-alist (bmkp-sort-omit bookmark-alist
+ (and (not (eq bmkp-bmenu-filter-function
+ 'bmkp-omitted-alist-only))
+ bmkp-bmenu-omitted-bookmarks)))
+ (dolist (bmk bmkp-sorted-alist)
+ (setq max-width (max max-width (string-width (bmkp-bookmark-name-from-record bmk)))))
+ (setq max-width (+ max-width bmkp-bmenu-marks-width))
+ (dolist (bmk bmkp-sorted-alist)
+ (setq name (bmkp-bookmark-name-from-record bmk)
+ markedp (bmkp-marked-bookmark-p bmk)
+ flaggedp (bmkp-flagged-bookmark-p bmk)
+ tags (bmkp-get-tags bmk)
+ annotation (bookmark-get-annotation bmk)
+ start (+ bmkp-bmenu-marks-width (point)))
+ (cond (flaggedp (insert "D") (put-text-property (1- (point)) (point) 'face 'bmkp-D-mark))
+ (markedp (insert ">") (put-text-property (1- (point)) (point) 'face 'bmkp->-mark))
+ (t (insert " ")))
+ (if (null tags)
+ (insert " ")
+ (insert "t") (put-text-property (1- (point)) (point) 'face 'bmkp-t-mark))
+ (cond ((bmkp-temporary-bookmark-p bmk)
+ (insert "X") (put-text-property (1- (point)) (point) 'face 'bmkp-X-mark))
+ ((and annotation (not (string-equal annotation "")))
+ (insert "a") (put-text-property (1- (point)) (point) 'face 'bmkp-a-mark))
+ (t (insert " ")))
+ (if (not (memq bmk bmkp-modified-bookmarks))
+ (insert " ")
+ (insert "*")
+ (put-text-property (1- (point)) (point) 'face 'bmkp-*-mark))
+ (when (and (featurep 'bookmark+-lit) (bmkp-get-lighting bmk)) ; Highlight highlight overrides.
+ (put-text-property (1- (point)) (point) 'face 'bmkp-light-mark))
+ (when (and (bmkp-image-bookmark-p bmk) show-image-file-icon-p)
+ (let ((image (create-image bmkp-bmenu-image-bookmark-icon-file nil nil :ascent 95)))
+ (when image (put-image image (point)))))
+ (insert name)
+ (move-to-column max-width t)
+ (bmkp-bmenu-propertize-item bmk start (point))
+ (insert "\n")))
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (bookmark-bmenu-mode)
+ (when (and bookmark-alist bookmark-bmenu-toggle-filenames)
+ (bookmark-bmenu-toggle-filenames t 'NO-MSG-P))
+ (when (and (fboundp 'fit-frame-if-one-window)
+ (eq (selected-window) (get-buffer-window (get-buffer-create bmkp-bmenu-buffer) 0)))
+ (fit-frame-if-one-window)))
+ (when (fboundp 'bmkp-bmenu-mode-line) (bmkp-bmenu-mode-line))
+ (when (and interactivep bmkp-sort-comparer) (bmkp-msg-about-sort-order (bmkp-current-sort-order))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; Redefined.
+;; 1. Get name of the current bookmark from text property `bmkp-bookmark-name'.
+;; 2. Added optional arg FULL, to return full bookmark record.
+;; 3. Use `condition-case' in case we're at eob (so cannot advance).
+;;
+(defun bookmark-bmenu-bookmark (&optional full)
+ "Return the name of the bookmark on this line.
+Normally, the string returned is propertized with property
+`bmkp-full-record', which records the full bookmark record.
+Return nil if no bookmark on this line.
+Non-nil optional FULL means return the bookmark record, not the name."
+ (condition-case nil
+ (let ((name (save-excursion (forward-line 0) (forward-char bmkp-bmenu-marks-width)
+ (get-text-property (point) 'bmkp-bookmark-name))))
+ (if full (get-text-property 0 'bmkp-full-record name) name))
+ (error nil)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Mode-line major-mode name is different, and indicates whether in temporary bookmarking minor mode.
+;; 2. Doc string is different.
+;;
+(defun bookmark-bmenu-mode ()
+ "Major mode for editing a list of bookmarks.
+
+Each line represents an Emacs bookmark. Keys without prefix `C-x' are
+available only here (in `*Bookmark List*'). Other keys are available
+everywhere.
+
+Remember that you can see all bindings for a prefix key by hitting it,
+then `C-h'. E.g., `s C-h' to see keys with prefix `s' (sorting keys).
+
+More bookmarking help below.
+
+
+Help - Bookmark Info
+--------------------
+
+\\<bookmark-bmenu-mode-map>\
+\\[bookmark-bmenu-toggle-filenames]\t- Toggle showing filenames next to bookmarks
+\\[bmkp-bmenu-describe-this-bookmark]\t- Show information about bookmark (`C-u': internal form)
+\\[bmkp-bmenu-describe-this+move-down]\t- Show the info, then move to next bookmark
+\\[bmkp-bmenu-describe-this+move-up]\t- Show the info, then move to previous bookmark
+\\[bmkp-bmenu-describe-marked]\t- Show info about the marked bookmarks (`C-u': internal form)
+\\[bookmark-bmenu-locate]\t- Show location of bookmark (in minibuffer)
+\\[bookmark-bmenu-show-annotation]\t- Show bookmark's annotation
+\\[bookmark-bmenu-show-all-annotations]\t- Show the annotations of all annotated bookmarks
+
+\\[bmkp-list-defuns-in-commands-file]
+\t- List the commands defined in `bmkp-bmenu-commands-file'
+
+
+Bookmark-List Display (`*Bookmark List*')
+-----------------------------------------
+
+\\[bmkp-toggle-saving-menu-list-state]\t- Toggle autosaving bookmark-list display state
+\\[bmkp-save-menu-list-state]\t- Save bookmark-list display state
+
+\\[bmkp-bmenu-refresh-menu-list]\t- Refresh display to current bookmark list (`C-u': from file)
+\\[bmkp-bmenu-show-all]\t- Show all bookmarks
+\\[bmkp-toggle-bookmark-set-refreshes]
+\t- Toggle whether `bookmark-set' refreshes the bookmark list
+\\[bmkp-bmenu-mode-status-help]\t- Show this help
+\\[bmkp-bmenu-quit]\t- Quit (`*Bookmark List*')
+
+
+Bookmark Files
+--------------
+
+\\[bmkp-toggle-saving-bookmark-file]\t- Toggle autosaving to the current bookmark file
+\\[bookmark-bmenu-save]\t- Save bookmarks now (`C-u': Save As... - prompt for file)
+\\[bmkp-empty-file]\t- Empty existing bookmark file or create new, empty one
+
+C-u \\[bmkp-bmenu-refresh-menu-list]\t- Revert to bookmarks in the bookmark file (overwrite load)
+\\[bmkp-switch-bookmark-file-create]\t- Switch to a different bookmark file (overwrite load)
+C-u \\[bmkp-switch-bookmark-file-create]\t- Switch back to the previous bookmark file (overwrite load)
+\\[bookmark-bmenu-load]\t- Add bookmarks from a different bookmark file (extra load)
+\\[bmkp-bmenu-load-marked-bookmark-file-bookmarks]\t- Load marked bookmark-file bookmarks \
+\(extra load)
+
+\\[bmkp-bmenu-move-marked-to-bookmark-file]\t- Move the marked bookmarks to a bookmark file
+\\[bmkp-bmenu-copy-marked-to-bookmark-file]\t- Copy the marked bookmarks to a bookmark file
+\\[bmkp-bmenu-create-bookmark-file-from-marked]\t- Copy the marked bookmarks to a new bookmark file
+C-u \\[bmkp-bmenu-create-bookmark-file-from-marked]\t- Same, plus create bookmark-file bookmark for it
+
+
+General
+-------
+
+Here:
+
+\\[bmkp-bmenu-dired-marked]\t- Open Dired for the marked file and directory bookmarks
+\\[bmkp-bmenu-make-sequence-from-marked]
+\t- Create a sequence bookmark from the marked bookmarks
+\\[bmkp-temporary-bookmarking-mode]\t- Toggle temporary-only bookmarking (new, empty bookmark file)
+
+Anywhere:
+
+\\<global-map>\
+\\[bmkp-toggle-autotemp-on-set]\t- Toggle making bookmarks temporary when setting them
+\\[bmkp-set-bookmark-file-bookmark]\t- Create a bookmark to a bookmark file (`j y' to load it)
+\\[bmkp-delete-bookmarks]\t- Delete some bookmarks at point or all in buffer
+\\[bmkp-make-function-bookmark]\t- Create a function bookmark
+
+\\[bmkp-choose-navlist-of-type]\t- Set the navlist to the bookmarks of a type you choose
+\\[bmkp-choose-navlist-from-bookmark-list]\t- Set the navlist to the bookmarks of a \
+bookmark-list bookmark
+\\[bmkp-navlist-bmenu-list]\t- Open `*Bookmark List*' for bookmarks in navlist
+
+\\[bmkp-this-file/buffer-bmenu-list]\t- Open `*Bookmark List*' for bookmarks in current file/buffer
+\\[bmkp-switch-to-bookmark-file-this-file/buffer]\t- Switch to bookmark file for current file/buffer
+\\[bmkp-save-bookmarks-this-file/buffer]\t- Save bookmarks for current file/buffer to a file
+\\<bookmark-bmenu-mode-map>
+
+
+Create/Set Bookmarks (anywhere)
+--------------------
+
+\\[bmkp-toggle-autonamed-bookmark-set/delete]\t- Set/delete an autonamed bookmark here
+\\[bmkp-autofile-set]\t- Set and autoname a bookmark for a file
+\\[bmkp-file-target-set]\t- Set a bookmark for a file
+\\[bmkp-url-target-set]\t- Set a bookmark for a URL
+\\[bmkp-bookmark-set-confirm-overwrite]\t\t- Set a bookmark here
+\\[bmkp-set-desktop-bookmark]\t\t- Set a bookmark for the current desktop
+\\[bmkp-set-bookmark-file-bookmark]\t\t- Set a bookmark for a bookmark file
+\\[bmkp-set-snippet-bookmark]\t- Save the region text as a snippet bookmark
+
+
+Jump to (Visit) Bookmarks
+-------------------------
+
+\\[bookmark-bmenu-this-window]\t- This bookmark in the same window
+\\[bookmark-bmenu-other-window]\t- This bookmark in another window
+\\[bookmark-bmenu-switch-other-window]\t- This bookmark in other window, without selecting it
+\\[bookmark-bmenu-2-window]\t- This bookmark and last-visited bookmark
+\\[bookmark-bmenu-1-window]\t- This bookmark in a full-frame window
+\\[bookmark-bmenu-other-frame]\t- This bookmark in another frame
+
+\\[bmkp-bmenu-jump-to-marked]\t- Bookmarks marked `>', in other windows
+
+Prefix `j' uses another window; prefix `J' reuses this window:
+
+\\[bookmark-jump-other-window]\t- Bookmark by name
+\\[bmkp-jump-in-navlist-other-window]\t- Bookmark in the navigation list
+\\[bmkp-lighted-jump-other-window]\t- Highlighted bookmark
+
+\\[bmkp-jump-to-type-other-window]\t- Bookmark by type
+\\[bmkp-autonamed-jump-other-window]\t- Autonamed bookmark
+\\[bmkp-autonamed-this-buffer-jump-other-window]\t- Autonamed bookmark in this buffer
+\\[bmkp-temporary-jump-other-window]\t- Temporary bookmark
+
+\\[bmkp-autofile-jump-other-window]\t- Autofile bookmark
+\\[bmkp-dired-jump-other-window]\t- Dired bookmark
+\\[bmkp-file-jump-other-window]\t- File or directory bookmark
+\\[bmkp-dired-this-dir-jump-other-window]\t- Dired bookmark for this dir
+\\[bmkp-file-this-dir-jump-other-window]\t- Bookmark for a file or subdir in this dir
+\\[bmkp-local-file-jump-other-window]\t- Local-file bookmark
+\\[bmkp-remote-file-jump-other-window]\t- Remote-file bookmark
+\\[bmkp-non-file-jump-other-window]\t- Non-file (buffer) bookmark
+
+\\[bmkp-desktop-jump]\t- Desktop bookmark
+\\[bmkp-bookmark-list-jump]\t- Bookmark-list bookmark
+\\[bmkp-bookmark-file-jump]\t- Bookmark-file bookmark
+
+\\[bmkp-region-jump-other-window]\t- Region bookmark (restore region)
+\\[bmkp-snippet-to-kill-ring]\t- Snippet bookmark (copy to `kill-ring')
+\\[bmkp-image-jump-other-window]\t- Image-file bookmark
+\\[bmkp-info-jump-other-window]\t- Info bookmark
+\\[bmkp-man-jump-other-window]\t- `man'-page bookmark
+\\[bmkp-gnus-jump-other-window]\t- Gnus bookmark
+\\[bmkp-url-jump-other-window]\t- URL bookmark
+\\[bmkp-variable-list-jump]\t- Variable-list bookmark
+
+\\[bmkp-some-tags-jump-other-window]\t- Bookmark having some tags you specify
+\\[bmkp-all-tags-jump-other-window]\t- Bookmark having each tag you specify
+\\[bmkp-some-tags-regexp-jump-other-window]\t- Bookmark having a tag that matches a regexp
+\\[bmkp-all-tags-regexp-jump-other-window]\t- Bookmark having all its tags match a regexp
+\\[bmkp-file-some-tags-jump-other-window]\t- File bookmark having some tags you specify
+\\[bmkp-file-all-tags-jump-other-window]\t- File bookmark having each tag you specify
+\\[bmkp-file-some-tags-regexp-jump-other-window]\t- File bookmark having a tag that matches a regexp
+\\[bmkp-file-all-tags-regexp-jump-other-window]\t- File bookmark having all its tags match a regexp
+\\[bmkp-file-this-dir-some-tags-jump-other-window]\t- File in this dir having some tags you specify
+\\[bmkp-file-this-dir-all-tags-jump-other-window]\t- File in this dir having each tag you specify
+\\[bmkp-file-this-dir-some-tags-regexp-jump-other-window]\t- \
+File in this dir having a tag that matches a regexp
+\\[bmkp-file-this-dir-all-tags-regexp-jump-other-window]\t- \
+File in this dir having all its tags match a regexp
+
+
+Autonamed Bookmarks
+-------------------
+
+\\[bmkp-toggle-autonamed-bookmark-set/delete]\t- Create/delete autonamed bookmark at point
+C-u \\[bmkp-toggle-autonamed-bookmark-set/delete]\t- Delete all autonamed bookmarks in current buffer
+\\[bmkp-autonamed-jump-other-window]\t\t- Jump to an autonamed bookmark
+\\[bmkp-autonamed-this-buffer-jump-other-window]\t\t- Jump to an autonamed bookmark in a given buffer
+
+
+Cycle Bookmarks (anywhere)
+---------------
+
+\\[bmkp-next-bookmark-this-file/buffer-repeat]...\t- Next bookmark in buffer (C-x x n, C-x x C-n)
+\\[bmkp-previous-bookmark-this-file/buffer-repeat]...\t- Prev bookmark in buffer (C-x x p, \
+C-x x C-p)
+\\[bmkp-next-bookmark-repeat]...- Next bookmark in navlist (C-x x f, C-x x C-f)
+\\[bmkp-previous-bookmark-repeat]...\t- Prev bookmark in navlist (C-x x b, C-x x C-b)
+\\[bmkp-next-bookmark-w32-repeat]...\t- MS Windows `Open' next in navlist (C-x x next)
+\\[bmkp-previous-bookmark-w32-repeat]...- MS Windows `Open' previous in navlist (C-x x prior)
+\\[bmkp-next-lighted-this-buffer-repeat]...- Next highlighted bookmark in buffer (C-x x C-down)
+\\[bmkp-previous-lighted-this-buffer-repeat]...\t- Prev highlighted bookmark in buffer (C-x x C-up)
+
+ Similar, but not bound to keys by default:
+ \\[bmkp-next-autonamed-bookmark-repeat] (and `previous')
+ \\[bmkp-next-bookmark-list-bookmark-repeat] (and `previous')
+ \\[bmkp-next-desktop-bookmark-repeat] (and `previous')
+ \\[bmkp-next-dired-bookmark-repeat] (and `previous')
+ \\[bmkp-next-eww-bookmark-repeat] (and `previous')
+ \\[bmkp-next-file-bookmark-repeat] (and `previous')
+ \\[bmkp-next-gnus-bookmark-repeat] (and `previous')
+ \\[bmkp-next-info-bookmark-repeat] (and `previous')
+ \\[bmkp-next-lighted-bookmark-repeat] (and `previous')
+ \\[bmkp-next-local-file-bookmark-repeat] (and `previous')
+ \\[bmkp-next-man-bookmark-repeat] (and `previous')
+ \\[bmkp-next-non-file-bookmark-repeat] (and `previous')
+ \\[bmkp-next-remote-file-bookmark-repeat] (and `previous')
+ \\[bmkp-next-specific-buffers-bookmark-repeat] (and `previous')
+ \\[bmkp-next-specific-files-bookmark-repeat] (and `previous')
+ \\[bmkp-next-url-bookmark-repeat] (and `previous')
+ \\[bmkp-next-variable-list-bookmark-repeat] (and `previous')
+
+
+Search-and-Replace in Bookmark Targets (here, in sort order)
+--------------------------------------
+
+\\[bmkp-bmenu-isearch-marked-bookmarks]\t- Isearch the marked bookmarks (`C-u': all)
+\\[bmkp-bmenu-isearch-marked-bookmarks-regexp]\t- Regexp-isearch the marked bookmarks (`C-u': all)
+\\[bmkp-bmenu-search-marked-bookmarks-regexp]\t- Regexp-search the marked file bookmarks (`C-u': all)
+\\[bmkp-bmenu-query-replace-marked-bookmarks-regexp]\t\t- Query-replace the marked file bookmarks
+
+
+Mark/Unmark Bookmarks
+---------------------
+
+\(Mark means `>'. Flag means `D'. See also `Tags', below.)
+
+\\[bmkp-bmenu-flag-for-deletion]\t- Flag bookmark `D' for deletion, then move down
+\\[bmkp-bmenu-flag-for-deletion-backwards]\t- Flag bookmark `D' for deletion, then move up
+
+\\[bookmark-bmenu-mark]\t- Mark bookmark
+\\[bookmark-bmenu-unmark]\t- Unmark bookmark (`C-u': move up one line)
+\\[bookmark-bmenu-backup-unmark]\t- Unmark previous bookmark (move up, then unmark)
+
+\\[bmkp-bmenu-mark-all]\t- Mark all bookmarks
+\\[bmkp-bmenu-regexp-mark]\t- Mark all bookmarks whose names match a regexp
+\\[bmkp-bmenu-unmark-all]\t- Unmark all bookmarks (`C-u': interactive query)
+\\[bmkp-bmenu-toggle-marks]\t- Toggle marks: unmark the marked and mark the unmarked
+
+\\[bmkp-bmenu-mark-autofile-bookmarks]\t- Mark autofile bookmarks
+\\[bmkp-bmenu-mark-autonamed-bookmarks]\t- Mark autonamed bookmarks
+\\[bmkp-bmenu-mark-temporary-bookmarks]\t- Mark temporary bookmarks
+\\[bmkp-bmenu-mark-lighted-bookmarks]\t- Mark highlighted bookmarks (requires `bookmark+-lit.el)
+
+\\[bmkp-bmenu-mark-non-file-bookmarks]\t- Mark non-file (i.e. buffer) bookmarks
+\\[bmkp-bmenu-mark-dired-bookmarks]\t- Mark Dired bookmarks
+\\[bmkp-bmenu-mark-file-bookmarks]\t- Mark file & directory bookmarks (`C-u': local only)
+\\[bmkp-bmenu-mark-gnus-bookmarks]\t- Mark Gnus bookmarks
+\\[bmkp-bmenu-mark-info-bookmarks]\t- Mark Info bookmarks
+\\[bmkp-bmenu-mark-icicles-search-hits-bookmarks]\t- Mark Icicles search-hits bookmarks
+\\[bmkp-bmenu-mark-non-invokable-bookmarks]\t- Mark non-invokable bookmarks
+\\[bmkp-bmenu-mark-image-bookmarks]\t- Mark image-file bookmarks
+\\[bmkp-bmenu-mark-desktop-bookmarks]\t- Mark desktop bookmarks
+\\[bmkp-bmenu-mark-man-bookmarks]\t- Mark `man' page bookmarks (that's `M' twice, not Meta-M)
+\\[bmkp-bmenu-mark-orphaned-local-file-bookmarks]\t- Mark orphaned local file/dir bookmarks (`C-u': \
+remote also)
+\\[bmkp-bmenu-mark-region-bookmarks]\t- Mark region bookmarks
+\\[bmkp-bmenu-mark-function-bookmarks]\t- Mark function bookmarks
+\\[bmkp-bmenu-mark-url-bookmarks]\t- Mark URL bookmarks
+\\[bmkp-bmenu-mark-variable-list-bookmarks]\t- Mark variable-list bookmarks
+\\[bmkp-bmenu-mark-w3m-bookmarks]\t- Mark W3M (URL) bookmarks
+\\[bmkp-bmenu-mark-snippet-bookmarks]\t- Mark snippet bookmarks
+\\[bmkp-bmenu-mark-bookmark-file-bookmarks]\t- Mark bookmark-file bookmarks
+\\[bmkp-bmenu-mark-bookmark-list-bookmarks]\t- Mark bookmark-list bookmarks
+
+
+Modify, Delete Bookmarks
+------------------------
+
+\(See also `Tags', next.)
+
+\\[bmkp-bmenu-edit-bookmark-name-and-location]\t- Rename or relocate bookmark
+\\[bookmark-bmenu-relocate]\t- Relocate bookmark
+\\[bmkp-bmenu-relocate-marked]\t- Relocate marked bookmarks
+\\[bmkp-bmenu-edit-tags]\t- Edit bookmark's tags
+\\[bookmark-bmenu-edit-annotation]\t- Edit bookmark's annotation
+\\[bmkp-bmenu-edit-annotations-for-marked]\t- Edit annotations of marked bookmarks (`C-u': all)
+\\[bmkp-bmenu-edit-bookmark-record]\t- Edit internal Lisp record for bookmark
+\\[bmkp-bmenu-edit-marked]\t- Edit internal Lisp records of marked bookmarks (`C-u': all)
+\\[bmkp-bmenu-toggle-temporary]\t- Toggle temporary/savable status of bookmark
+\\[bmkp-bmenu-toggle-marked-temporary/savable]\t- Toggle temporary/savable status of marked bookmarks
+\\[bmkp-delete-all-temporary-bookmarks]\t- Delete all temp bookmarks
+\\[bookmark-bmenu-execute-deletions]\t- Delete (visible) bookmarks flagged `D'
+\\[bmkp-bmenu-delete-marked]\t- Delete (visible) bookmarks marked `>'
+
+
+Bookmark Tags
+-------------
+
+Here:
+
+\\[bmkp-bmenu-copy-tags]\t- Copy tags from this bookmark (for subsequent pasting)
+\\[bmkp-bmenu-paste-add-tags]\t- Paste tags (copied from another) to this bookmark
+\\[bmkp-bmenu-paste-replace-tags]\t- Replace tags for this bookmark (with those copied)
+\\[bmkp-add-tags]\t- Add some tags to a bookmark
+\\[bmkp-remove-tags]\t- Remove some tags from a bookmark (`C-u': from all bookmarks)
+\\[bmkp-remove-all-tags]\t- Remove all tags from a bookmark
+\\[bmkp-remove-tags-from-all]\t- Remove some tags from all bookmarks
+\\[bmkp-rename-tag]\t- Rename a tag in all bookmarks
+\\[bmkp-list-all-tags]\t- List all tags used in any bookmarks (`C-u': show tag values)
+\\[bmkp-bmenu-list-tags-of-marked]\t- List tags used in marked bookmarks (`C-u': show tag values)
+\\[bmkp-bmenu-edit-tags]\t- Edit bookmark's tags
+\\[bmkp-bmenu-set-tag-value]\t- Set the value of a tag (as attribute)
+
+\\[bmkp-bmenu-set-tag-value-for-marked]\t- Set value of a tag, for each marked bookmark (`C-u': all)
+\\[bmkp-bmenu-paste-add-tags-to-marked]\t- Add tags copied from a bookmark to those marked (`C-u': all)
+\\[bmkp-bmenu-paste-replace-tags-for-marked]\t- Replace tags of marked with copied tags \
+ (`C-u': all)
+\\[bmkp-bmenu-add-tags-to-marked]\t- Add some tags to the marked bookmarks (`C-u': all)
+\\[bmkp-bmenu-remove-tags-from-marked]\t- Remove some tags from the marked bookmarks (`C-u': all)
+
+\\[bmkp-bmenu-mark-bookmarks-tagged-regexp]\t- Mark bookmarks having at least one \
+tag that matches a regexp
+\\[bmkp-bmenu-mark-bookmarks-tagged-some]\t- Mark bookmarks having at least one tag \
+in a set (OR)
+\\[bmkp-bmenu-mark-bookmarks-tagged-all]\t- Mark bookmarks having all of the tags \
+in a set (AND)
+\\[bmkp-bmenu-mark-bookmarks-tagged-none]\t- Mark bookmarks not having any of the tags \
+in a set (NOT OR)
+\\[bmkp-bmenu-mark-bookmarks-tagged-not-all]\t- Mark bookmarks not having all of the \
+tags in a set (NOT AND)
+
+\\[bmkp-bmenu-unmark-bookmarks-tagged-regexp]\t- Unmark bookmarks having a \
+tag that matches a regexp
+\\[bmkp-bmenu-unmark-bookmarks-tagged-some]\t- Unmark bookmarks having at least one \
+tag in a set (OR)
+\\[bmkp-bmenu-unmark-bookmarks-tagged-all]\t- Unmark bookmarks having all of the tags \
+in a set (AND)
+\\[bmkp-bmenu-unmark-bookmarks-tagged-none]\t- Unmark bookmarks not having any tags \
+in a set (NOT OR)
+\\[bmkp-bmenu-unmark-bookmarks-tagged-not-all]\t- Unmark bookmarks not having all tags \
+in a set (NOT AND)
+
+Anywhere:
+
+\\<global-map>\
+\\[bmkp-list-all-tags]\t- List all tags
+\\[bmkp-edit-tags]\t- Edit the tags of a bookmark
+\\[bmkp-rename-tag]\t- Rename a tag (everywhere)
+\\[bmkp-copy-tags]\t- Copy tags from a bookmark (for subsequent pasting)
+\\[bmkp-paste-add-tags]\t- Add (paste) tags copied from a bookmark
+\\[bmkp-paste-replace-tags]\t- Replace (paste) a bookmark's tags with copied tags
+\\[bmkp-add-tags]\t- Add some tags to a bookmark
+\\[bmkp-remove-tags]\t- Remove some tags from a bookmark
+\\[bmkp-remove-all-tags]\t- Remove ALL tags from a bookmark
+\\[bmkp-remove-tags-from-all]\t- Remove some tags from ALL bookmarks
+\\[bmkp-tag-a-file]\t- Add tags to a file (create/update autofile bookmark)
+\\[bmkp-untag-a-file]\t- Remove tags from a file (an autofile bookmark)
+\\[bmkp-set-tag-value]\t- Set a tag value for a bookmark
+\\[bmkp-set-tag-value-for-navlist]\t- Set a tag value for each bookmark in navlist
+\\<bookmark-bmenu-mode-map>
+
+
+Bookmark Highlighting
+---------------------
+
+\\[bmkp-bmenu-show-only-lighted-bookmarks]\t- Show only the highlighted bookmarks
+\\[bmkp-bmenu-set-lighting]\t- Set highlighting for bookmark
+\\[bmkp-bmenu-set-lighting-for-marked]\t- Set highlighting for marked bookmarks
+\\[bmkp-bmenu-light]\t- Highlight bookmark
+\\[bmkp-bmenu-unlight]\t- Unhighlight bookmark
+\\[bmkp-bmenu-mark-lighted-bookmarks]\t- Mark the highlighted bookmarks
+\\[bmkp-bmenu-light-marked]\t- Highlight the marked bookmarks
+\\[bmkp-bmenu-unlight-marked]\t- Unhighlight the marked bookmarks
+\\[bmkp-light-bookmark-this-buffer]\t- Highlight a bookmark in current buffer
+\\[bmkp-unlight-bookmark-this-buffer]\t- Unhighlight a bookmark in current buffer
+\\[bmkp-light-bookmarks]\t- Highlight bookmarks (see prefix arg)
+\\[bmkp-unlight-bookmarks]\t- Unhighlight bookmarks (see prefix arg)
+\\[bmkp-bookmarks-lighted-at-point]\t- List bookmarks highlighted at point
+\\[bmkp-unlight-bookmark-here]\t- Unhighlight a bookmark at point or on same line
+\\[bmkp-lighted-jump-other-window]\t- Jump to a highlighted bookmark (other window)
+
+
+Sort `*Bookmark List*' (`s C-h' to see this)
+----------------------
+
+\(Repeat to cycle normal/reversed/off, except as noted.)
+
+\\[bmkp-reverse-sort-order]\t- Reverse current sort direction (repeat to toggle)
+\\[bmkp-reverse-multi-sort-order]\t- Complement sort predicate decisions (repeat \
+to toggle)
+\\[bmkp-bmenu-change-sort-order-repeat]\t- Cycle sort orders (repeat \
+to cycle)
+
+\\[bmkp-bmenu-sort-marked-before-unmarked]\t- Sort marked (`>') bookmarks first
+\\[bmkp-bmenu-sort-flagged-before-unflagged]\t- Sort flagged (`D') bookmarks first
+\\[bmkp-bmenu-sort-modified-before-unmodified]\t- Sort modified (`*') bookmarks first
+\\[bmkp-bmenu-sort-tagged-before-untagged]\t- Sort tagged (`t') bookmarks first
+\\[bmkp-bmenu-sort-annotated-before-unannotated]\t- Sort annotated (`a') bookmarks first
+
+\\[bmkp-bmenu-sort-by-creation-time]\t- Sort by bookmark creation time
+\\[bmkp-bmenu-sort-by-last-buffer-or-file-access]\t- Sort by last buffer or file \
+access
+\\[bmkp-bmenu-sort-by-last-bookmark-access]\t- Sort by last bookmark access time
+\\[bmkp-bmenu-sort-by-Gnus-thread]\t- Sort by Gnus thread: group, article, message
+\\[bmkp-bmenu-sort-by-Info-node-name]\t- Sort by Info manual, node, position in node
+\\[bmkp-bmenu-sort-by-Info-position]\t- Sort by Info manual, position in manual
+\\[bmkp-bmenu-sort-by-bookmark-type]\t- Sort by bookmark type
+\\[bmkp-bmenu-sort-by-bookmark-name]\t- Sort by bookmark name
+\\[bmkp-bmenu-sort-by-url]\t- Sort by URL
+\\[bmkp-bmenu-sort-by-bookmark-visit-frequency]\t- Sort by bookmark visit frequency
+
+\\[bmkp-bmenu-sort-by-last-local-file-access]\t- Sort by last local file access
+\\[bmkp-bmenu-sort-by-local-file-type]\t- Sort by local file type: file, symlink, dir
+\\[bmkp-bmenu-sort-by-file-name]\t- Sort by file name
+\\[bmkp-bmenu-sort-by-local-file-size]\t- Sort by local file size
+\\[bmkp-bmenu-sort-by-last-local-file-update]\t- Sort by last local file update (edit)
+
+
+Hide/Show (Filtering `*Bookmark List*')
+---------------------------------------
+
+\\[bmkp-bmenu-show-all]\t- Show all bookmarks
+\\[bmkp-bmenu-toggle-show-only-marked]\t- Toggle showing only marked bookmarks
+\\[bmkp-bmenu-toggle-show-only-unmarked]\t- Toggle showing only unmarked bookmarks
+
+\\[bmkp-bmenu-show-only-autonamed-bookmarks]\t- Show only autonamed bookmarks
+\\[bmkp-bmenu-show-only-autofile-bookmarks]\t- Show only autofile bookmarks
+\\[bmkp-bmenu-show-only-temporary-bookmarks]\t- Show only temporary bookmarks
+
+\\[bmkp-bmenu-show-only-non-file-bookmarks]\t- Show only non-file (i.e. buffer) bookmarks
+\\[bmkp-bmenu-show-only-dired-bookmarks]\t- Show only Dired bookmarks
+\\[bmkp-bmenu-show-only-file-bookmarks]\t- Show only file & directory bookmarks (`C-u': local only)
+\\[bmkp-bmenu-show-only-gnus-bookmarks]\t- Show only Gnus bookmarks
+\\[bmkp-bmenu-show-only-info-bookmarks]\t- Show only Info bookmarks
+\\[bmkp-bmenu-show-only-icicles-search-hits-bookmarks]\t- Show only Icicles search-hits bookmarks
+\\[bmkp-bmenu-show-only-non-invokable-bookmarks]\t- Show only non-invokable bookmarks
+\\[bmkp-bmenu-show-only-image-bookmarks]\t- Show only image-file bookmarks
+\\[bmkp-bmenu-show-only-orphaned-local-file-bookmarks]\t- Show only orphaned local file \
+bookmarks (`C-u': remote also)
+\\[bmkp-bmenu-show-only-desktop-bookmarks]\t- Show only desktop bookmarks
+\\[bmkp-bmenu-show-only-man-bookmarks]\t- Show only `man' page bookmarks
+\\[bmkp-bmenu-show-only-region-bookmarks]\t- Show only region bookmarks
+\\[bmkp-bmenu-show-only-function-bookmarks]\t- Show only function bookmarks
+\\[bmkp-bmenu-show-only-url-bookmarks]\t- Show only URL bookmarks
+\\[bmkp-bmenu-show-only-eww-bookmarks]\t- Show only EWW bookmarks
+\\[bmkp-bmenu-show-only-w3m-bookmarks]\t- Show only W3M bookmarks
+\\[bmkp-bmenu-show-only-variable-list-bookmarks]\t- Show only variable-list bookmarks
+\\[bmkp-bmenu-show-only-tagged-bookmarks]\t- Show only tagged bookmarks
+\\[bmkp-bmenu-show-only-untagged-bookmarks]\t- Show only untagged bookmarks
+\\[bmkp-bmenu-show-only-snippet-bookmarks]\t- Show only snippet bookmarks
+\\[bmkp-bmenu-show-only-bookmark-file-bookmarks]\t- Show only bookmark-file bookmarks
+\\[bmkp-bmenu-show-only-bookmark-list-bookmarks]\t- Show only bookmark-list bookmarks
+
+\\[bmkp-bmenu-filter-annotation-incrementally]\t- Incrementally show bookmarks whose \
+annotations match regexp
+\\[bmkp-bmenu-filter-bookmark-name-incrementally]\t- Incrementally show only bookmarks \
+whose names match a regexp
+\\[bmkp-bmenu-filter-file-name-incrementally]\t- Incrementally show only bookmarks whose \
+files match a regexp
+\\[bmkp-bmenu-filter-tags-incrementally]\t- Incrementally show only bookmarks whose tags \
+match a regexp
+
+
+Omit/Un-omit (`*Bookmark List*')
+--------------------------------
+
+\\[bmkp-bmenu-show-only-omitted-bookmarks]\t- Show (only) the omitted bookmarks
+\\[bmkp-bmenu-show-all]\t- Show the un-omitted bookmarks (all)
+\\[bmkp-bmenu-omit/unomit-marked]\t- Omit the marked bookmarks; un-omit them if after \
+`\\[bmkp-bmenu-show-only-omitted-bookmarks]'
+\\[bmkp-unomit-all]\t- Un-omit all omitted bookmarks
+
+
+Define Commands for `*Bookmark List*'
+-------------------------------------
+
+\\[bmkp-bmenu-define-command]\t- Define a command to restore the current sort order & filter
+\\[bmkp-bmenu-define-full-snapshot-command]\t- Define a command to restore current bookmark list
+\\[bmkp-define-tags-sort-command]\t- Define a command to sort bookmarks by tags
+\\[bmkp-bmenu-define-jump-marked-command]\t- Define a command to jump to a bookmark that is \
+now marked
+
+
+Options for `*Bookmark List*'
+-----------------------------
+
+bookmark-bmenu-file-column - Bookmark width if files are shown
+bookmark-bmenu-toggle-filenames - Show filenames initially?
+
+bmkp-bmenu-omitted-bookmarks - List of omitted bookmarks
+bmkp-bmenu-state-file - File to save bookmark-list state
+ (\"home\") nil: do not save/restore
+bmkp-sort-comparer - Initial sort
+bmkp-sort-orders-for-cycling-alist - Sort orders that `\\[bmkp-bmenu-change-sort-order-repeat]'... cycles
+
+
+Other Options
+-------------
+
+bookmark-automatically-show-annotations - Show annotation when visit?
+bookmark-completion-ignore-case - Case-sensitive completion?
+bookmark-default-file - File to save bookmarks in
+bookmark-menu-length - Max size of bookmark-name menu item
+bookmark-save-flag - Whether and when to save
+bookmark-use-annotations - Edit annotation when set bookmark?
+bookmark-version-control - Numbered backups of bookmark file?
+
+bmkp-autoname-format - Format of autonamed bookmark name
+bmkp-last-as-first-bookmark-file - Whether to start with last b. file
+bmkp-crosshairs-flag - Highlight position when visit?
+bmkp-menu-popup-max-length - Use menus to choose bookmarks?
+bmkp-save-new-location-flag - Save if bookmark relocated?
+bmkp-sequence-jump-display-function - How to display a sequence
+bmkp-sort-comparer - Predicates for sorting bookmarks
+bmkp-su-or-sudo-regexp - Bounce-show each end of region?
+bmkp-this-file/buffer-cycle-sort-comparer - cycling sort for here
+bmkp-use-region - Activate saved region when visit?"
+ (kill-all-local-variables)
+ (use-local-map bookmark-bmenu-mode-map)
+ (setq truncate-lines t
+ buffer-read-only t
+ major-mode 'bookmark-bmenu-mode
+ mode-name (if bmkp-temporary-bookmarking-mode "TEMPORARY Bookmarking" "Bookmarks"))
+ (if (fboundp 'run-mode-hooks)
+ (run-mode-hooks 'bookmark-bmenu-mode-hook)
+ (run-hooks 'bookmark-bmenu-mode-hook)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Corrected (rewrote). Toggle var first (unless SHOW). Call fn according to the var (& to SHOW).
+;; 2. Added optional arg NO-MSG-P.
+;;
+(defun bookmark-bmenu-toggle-filenames (&optional show no-msg-p)
+ "Toggle whether filenames are shown in the bookmark list.
+Toggle the value of `bookmark-bmenu-toggle-filenames', unless SHOW is
+non-nil.
+Optional argument SHOW means show them unconditionally.
+
+Non-nil optional arg NO-MSG-P means do not show progress messages."
+ (interactive)
+ (unless show (setq bookmark-bmenu-toggle-filenames (not bookmark-bmenu-toggle-filenames)))
+ (let ((bookmark-bmenu-toggle-filenames (or show bookmark-bmenu-toggle-filenames)))
+ (if bookmark-bmenu-toggle-filenames
+ (bookmark-bmenu-show-filenames nil no-msg-p)
+ (bookmark-bmenu-hide-filenames nil no-msg-p))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Put `mouse-face' on whole line, with the same help-echo as for the bookmark name.
+;; 2. Correct FORCE behavior.
+;; 3. Correct doc string.
+;; 4. Added optional arg NO-MSG-P and progress message.
+;; 5. Fit one-window frame.
+;;
+(defun bookmark-bmenu-show-filenames (&optional force no-msg-p)
+ "Show file names if `bookmark-bmenu-toggle-filenames' is non-nil.
+Otherwise do nothing, except non-nil optional argument FORCE has the
+same effect as non-nil `bookmark-bmenu-toggle-filenames'. FORCE is
+mainly for debugging.
+Non-nil optional arg NO-MSG-P means do not show progress messages."
+ (when (or force bookmark-bmenu-toggle-filenames)
+ (unless no-msg-p (message "Showing file names..."))
+ (with-buffer-modified-unmodified
+ (save-excursion
+ (save-window-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (setq bookmark-bmenu-hidden-bookmarks ())
+ (let ((inhibit-read-only t))
+ (while (< (point) (point-max))
+ (let ((bmk (bookmark-bmenu-bookmark)))
+ (setq bookmark-bmenu-hidden-bookmarks (cons bmk bookmark-bmenu-hidden-bookmarks))
+ (move-to-column bookmark-bmenu-file-column t)
+ (delete-region (point) (line-end-position))
+ (insert " ")
+ (bookmark-insert-location bmk t) ; Pass the NO-HISTORY arg.
+ (when (if (fboundp 'display-color-p) ; Emacs 21+.
+ (and (display-color-p) (display-mouse-p))
+ window-system)
+ (let ((help (get-text-property (+ bmkp-bmenu-marks-width (line-beginning-position))
+ 'help-echo)))
+ (put-text-property (+ bmkp-bmenu-marks-width (line-beginning-position))
+ (point) 'mouse-face 'highlight)
+ (when help (put-text-property (+ bmkp-bmenu-marks-width (line-beginning-position))
+ (point) 'help-echo help))))
+ (forward-line 1)))))))
+ (unless no-msg-p (message "Showing file names...done"))
+ (when (and (fboundp 'fit-frame-if-one-window)
+ (eq (selected-window) (get-buffer-window (get-buffer-create bmkp-bmenu-buffer) 0)))
+ (fit-frame-if-one-window))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Add text properties when hiding filenames.
+;; 2. Do not set or use `bookmark-bmenu-bookmark-column' - use `bmkp-bmenu-marks-width' always.
+;; 3. Correct FORCE behavior.
+;; 4. Correct doc string.
+;; 5. Added optional arg NO-MSG-P and progress message.
+;; 6. Fit one-window frame.
+;;
+(defun bookmark-bmenu-hide-filenames (&optional force no-msg-p)
+ "Hide filenames if `bookmark-bmenu-toggle-filenames' is nil.
+Otherwise do nothing, except non-nil optional argument FORCE has the
+same effect as nil `bookmark-bmenu-toggle-filenames'. FORCE is mainly
+for debugging.
+Non-nil optional arg NO-MSG-P means do not show progress messages."
+ (when (or force (not bookmark-bmenu-toggle-filenames))
+ (unless no-msg-p (message "Hiding file names..."))
+ (with-buffer-modified-unmodified
+ (save-excursion
+ (save-window-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (setq bookmark-bmenu-hidden-bookmarks (nreverse bookmark-bmenu-hidden-bookmarks))
+ (let ((max-width 0))
+ (dolist (name bookmark-bmenu-hidden-bookmarks)
+ (setq max-width (max max-width (string-width name))))
+ (setq max-width (+ max-width bmkp-bmenu-marks-width))
+ (save-excursion
+ (let ((inhibit-read-only t))
+ (while bookmark-bmenu-hidden-bookmarks
+ (move-to-column bmkp-bmenu-marks-width t)
+ (bookmark-kill-line)
+ (let ((name (car bookmark-bmenu-hidden-bookmarks))
+ (start (point))
+ end)
+ (insert name)
+ (move-to-column max-width t)
+ (setq end (point))
+ (bmkp-bmenu-propertize-item name start end))
+ (setq bookmark-bmenu-hidden-bookmarks (cdr bookmark-bmenu-hidden-bookmarks))
+ (forward-line 1))))))))
+ (unless no-msg-p (message "Hiding file names...done"))
+ (when (and (fboundp 'fit-frame-if-one-window)
+ (eq (selected-window) (get-buffer-window (get-buffer-create bmkp-bmenu-buffer) 0)))
+ (fit-frame-if-one-window))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Prefix arg reverses `bmkp-use-region'.
+;; 2. Raise error if not in buffer `*Bookmark List*'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-1-window "bookmark+")
+(defun bookmark-bmenu-1-window (&optional flip-use-region-p) ; Bound to `1' in bookmark list
+ "Select this line's bookmark, alone, in full frame.
+See `bookmark-jump' for info about the prefix arg."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (bmkp-jump-1 (bookmark-bmenu-bookmark) 'pop-to-buffer flip-use-region-p)
+ (bury-buffer (other-buffer))
+ (delete-other-windows))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Prefix arg reverses `bmkp-use-region'.
+;; 2. Raise error if not in buffer `*Bookmark List*'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-2-window "bookmark+")
+(defun bookmark-bmenu-2-window (&optional flip-use-region-p) ; Bound to `2' in bookmark list
+ "Select this line's bookmark, with previous buffer in second window.
+See `bookmark-jump' for info about the prefix arg."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((bookmark-name (bookmark-bmenu-bookmark))
+ (menu (current-buffer))
+ (pop-up-windows t))
+ (delete-other-windows)
+ (bmkp--pop-to-buffer-same-window (other-buffer))
+ ;; (let ((bookmark-automatically-show-annotations nil)) ; $$$$$$ Needed?
+ (bmkp-jump-1 bookmark-name 'pop-to-buffer flip-use-region-p)
+ (bury-buffer menu)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Prefix arg reverses `bmkp-use-region'.
+;; 2. Raise error if not in buffer `*Bookmark List*'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-this-window "bookmark+")
+(defun bookmark-bmenu-this-window (&optional flip-use-region-p) ; Bound to `RET' in bookmark list
+ "Select this line's bookmark in this window.
+See `bookmark-jump' for info about the prefix arg."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((bookmark-name (bookmark-bmenu-bookmark)))
+ (bmkp-jump-1 bookmark-name 'bmkp--pop-to-buffer-same-window flip-use-region-p)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Use `pop-to-buffer', not `switch-to-buffer-other-window'.
+;; 2. Prefix arg reverses `bmkp-use-region'.
+;; 3. Raise error if not in buffer `*Bookmark List*'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-other-window "bookmark+")
+(defun bookmark-bmenu-other-window (&optional flip-use-region-p) ; Bound to `o' in bookmark list
+ "Select this line's bookmark in other window. Show `*Bookmark List*' still.
+See `bookmark-jump' for info about the prefix arg."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((bookmark-name (bookmark-bmenu-bookmark)))
+ ;; (bookmark-automatically-show-annotations t)) ; $$$$$$ Needed?
+ (bookmark-jump-other-window bookmark-name flip-use-region-p)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el' (Emacs 27+).
+;;
+;; 1. Use `pop-to-buffer', not `view-buffer-other-frame'.
+;; 2. Prefix arg reverses `bmkp-use-region'.
+;; 3. Raise error if not in buffer `*Bookmark List*'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-other-window "bookmark+")
+(defun bookmark-bmenu-other-frame (&optional flip-use-region-p) ; Bound to `j 5' in bookmark list
+ "Select this line's bookmark in another frame.
+See `bookmark-jump' for info about the prefix arg."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((bookmark-name (bookmark-bmenu-bookmark)))
+ ;; (bookmark-automatically-show-annotations t)) ; $$$$$$ Needed?
+ (bookmark-jump-other-frame bookmark-name flip-use-region-p)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Prefix arg reverses `bmkp-use-region'.
+;; 2. Raise error if not in buffer `*Bookmark List*'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-switch-other-window "bookmark+")
+(defun bookmark-bmenu-switch-other-window (&optional flip-use-region-p) ; Bound to `C-o' in bookmark list
+ "Make the other window select this line's bookmark.
+The current window remains selected.
+See `bookmark-jump' for info about the prefix arg."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((bookmark-name (bookmark-bmenu-bookmark))
+ (pop-up-windows t)
+ (same-window-buffer-names ())
+ (same-window-regexps ()))
+ ;; (bookmark-automatically-show-annotations t)) ; $$$$$$ Needed?
+ (bmkp-jump-1 bookmark-name 'display-buffer flip-use-region-p)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Prefix arg reverses `bmkp-use-region'.
+;; 2. Raise error if not in buffer `*Bookmark List*'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-other-window-with-mouse "bookmark+")
+(defun bookmark-bmenu-other-window-with-mouse (event &optional flip-use-region-p)
+ "Select clicked bookmark in other window. Show `*Bookmark List*' still.
+See `bookmark-jump' for info about the prefix arg."
+ (interactive "e\nP")
+ (with-current-buffer (window-buffer (posn-window (event-end event)))
+ (save-excursion (goto-char (posn-point (event-end event)))
+ (bookmark-bmenu-other-window flip-use-region-p))))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg MSG-P.
+;; 2. Call `bookmark-show-annotation' with arg MSG-P.
+;; 3. Raise error if not in buffer `*Bookmark List*'.
+;; 4. Doc string reflects enhanced behavior of `bookmark-show-annotation'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-show-annotation "bookmark+")
+(defun bookmark-bmenu-show-annotation (&optional msg-p) ; Bound to `a a' in bookmark list
+ "Show the annotation for the current bookmark, or follow it if external.
+If the annotation is external then jump to its destination.
+Non-interactively, non-nil MSG-P means display messages."
+ (interactive "p")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((bmk (bookmark-bmenu-bookmark)))
+ (unless bmk (error "No bookmark here"))
+ (bookmark-show-annotation bmk msg-p)))
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Added optional arg MARKEDP: handle bookmarks marked `>', not just those flagged `D'.
+;; 2. Added optional arg NO-CONFIRM-P.
+;; 3. Delete bookmark on current line (after confirmation) if none are flagged/marked.
+;; 4. Inhibit saving until all are deleted, then save all. This is because the Bookmark+ version of
+;; `bookmark-save' refreshes the bookmark list display, and that removes `D' flags.
+;; 5. Use `bmkp-get-bookmark' instead of `bookmark-get-bookmark', so we can get the right bookmarks when
+;; they have names with property `bmkp-full-record'. But don't require that they have names, so
+;; calls from vanilla or other code won't be bothered.
+;; 6. Use `bookmark-bmenu-surreptitiously-rebuild-list', instead of using
+;; `bookmark-bmenu-list', updating the modification count, and saving.
+;; 7. Update `bmkp-latest-bookmark-alist' to reflect the deletions.
+;; 8. Pass full bookmark, not name, to `delete' (and do not use `assoc').
+;; 9. Use `bmkp-bmenu-goto-bookmark-named'.
+;; 10. Added status messages.
+;; 11. Raise error if not in buffer `*Bookmark List*'.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-execute-deletions "bookmark+")
+(defun bookmark-bmenu-execute-deletions (&optional markedp no-confirm-p) ; Bound to `x' in bookmark list
+ "Delete (visible) bookmarks flagged `D', without confirmation.
+With a prefix argument, delete the bookmarks marked `>' instead, but
+only after confirmation.
+
+If NO bookmarks are flagged or marked (depending on whether a prefix
+arg was used), then delete the bookmark on this line, but only after
+confirmation.
+
+Non-interactively, optional arg NO-CONFIRM-P non-nil means do not ask
+for confirmation."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (if (and (null (if markedp bmkp-bmenu-marked-bookmarks bmkp-flagged-bookmarks))
+ (bookmark-bmenu-bookmark))
+ (if (progn (let ((visible-bell t)
+ (minibuffer-prompt-properties (append minibuffer-prompt-properties
+ '(face bmkp-*-mark))))
+ (ding) (ding)
+ (yes-or-no-p "DELETE THIS bookmark ")))
+ (bookmark-delete (bookmark-bmenu-bookmark))
+ (message "OK, not deleted"))
+ (if (or (not markedp)
+ no-confirm-p
+ (yes-or-no-p "Delete bookmarks marked `>' (not `D') "))
+ (let* ((mark-type (if markedp "^>" "^D"))
+ (o-str (and (not (bmkp-looking-at-p mark-type)) (bookmark-bmenu-bookmark)))
+ (o-point (point))
+ (count 0))
+ (message "Deleting bookmarks...")
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (while (re-search-forward mark-type (point-max) t)
+ (let* ((bmk-name (bookmark-bmenu-bookmark))
+ (bmk (bmkp-get-bookmark bmk-name nil 'NO-NAME-CHECK-P)))
+ ;; Inhibit saving until all are deleted, then do it once. Otherwise, some might not be
+ ;; deleted, because `bookmark-save' refreshes the list, which removes `D' flags.
+ (let ((bookmark-save-flag nil)) (bookmark-delete bmk-name 'BATCHP))
+ ;; Count is misleading if the bookmark is not really in `bookmark-alist'.
+ (setq count (1+ count)
+ bmkp-latest-bookmark-alist (delete bmk bmkp-latest-bookmark-alist))))
+ (bmkp-maybe-save-bookmarks) ; Do it now.
+ (if (<= count 0)
+ (message (if markedp "No marked bookmarks" "No bookmarks flagged for deletion"))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (message "Deleted %d bookmarks" count))
+ (if o-str
+ (bmkp-bmenu-goto-bookmark-named o-str)
+ (goto-char o-point)
+ (beginning-of-line)))
+ (message "OK, nothing deleted"))))
+
+
+
+;; REPLACES ORIGINAL in `bookmark.el'.
+;;
+;; 1. Do not call `bookmark-bmenu-list' (it was already called).
+;; 2. Raise error if not in buffer `*Bookmark List*'.
+;; 3. Use `bmkp-bmenu-goto-bookmark-named' instead of just searching for name.
+;;
+;;;###autoload (autoload 'bookmark-bmenu-rename "bookmark+")
+(defun bookmark-bmenu-rename () ; Bound to `r' in bookmark list
+ "Rename bookmark on current line. Prompts for a new name."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((newname (bookmark-rename (bookmark-bmenu-bookmark)))) (bmkp-bmenu-goto-bookmark-named newname)))
+
+;;(@* "Bookmark+ Functions (`bmkp-*')")
+;;; Bookmark+ Functions (`bmkp-*') -----------------------------------
+
+
+;;(@* "Menu-List (`*-bmenu-*') Filter Commands")
+;; *** Menu-List (`*-bmenu-*') Filter Commands ***
+
+;; `bmkp-bmenu-show-only-autonamed-bookmarks',
+;; `bmkp-bmenu-show-only-non-file-bookmarks',
+;; `bmkp-bmenu-show-only-dired-bookmarks',
+;; `bmkp-bmenu-show-only-eww-bookmarks' (Emacs 25+),
+;; `bmkp-bmenu-show-only-function-bookmarks',
+;; `bmkp-bmenu-show-only-gnus-bookmarks',
+;; `bmkp-bmenu-show-only-icicles-search-hits-bookmarks',
+;; `bmkp-bmenu-show-only-non-invokable-bookmarks',
+;; `bmkp-bmenu-show-only-image-bookmarks',
+;; `bmkp-bmenu-show-only-info-bookmarks',
+;; `bmkp-bmenu-show-only-desktop-bookmarks',
+;; `bmkp-bmenu-show-only-man-bookmarks',
+;; `bmkp-bmenu-show-only-region-bookmarks',
+;; `bmkp-bmenu-show-only-tagged-bookmarks',
+;; `bmkp-bmenu-show-only-untagged-bookmarks',
+;; `bmkp-bmenu-show-only-url-bookmarks',
+;; `bmkp-bmenu-show-only-variable-list-bookmarks',
+;; `bmkp-bmenu-show-only-snippet-bookmarks',
+;; `bmkp-bmenu-show-only-w3m-bookmarks',
+;; `bmkp-bmenu-show-only-temporary-bookmarks',
+;; `bmkp-bmenu-show-only-bookmark-file-bookmarks',
+;; `bmkp-bmenu-show-only-bookmark-list-bookmarks',
+
+
+;; The simple ones are defined using macro `bmkp-define-show-only-command'.
+;;
+;;;###autoload (autoload 'bmkp-bmenu-show-only-autonamed-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-non-file-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-dired-bookmarks "bookmark+")
+
+;; ;;;###autoload (autoload 'bmkp-bmenu-show-only-eww-bookmarks "bookmark+")
+
+;;;###autoload (autoload 'bmkp-bmenu-show-only-function-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-gnus-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-icicles-search-hits-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-non-invokable-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-image-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-info-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-desktop-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-man-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-region-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-tagged-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-untagged-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-url-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-variable-list-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-snippet-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-w3m-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-temporary-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-bookmark-file-bookmarks "bookmark+")
+;;;###autoload (autoload 'bmkp-bmenu-show-only-bookmark-list-bookmarks "bookmark+")
+
+;; Bindings indicated are in `*Bookmark List*'.
+(bmkp-define-show-only-command autonamed "Display (only) the autonamed bookmarks."
+ bmkp-autonamed-alist-only) ; `# S'
+(bmkp-define-show-only-command non-file "Display (only) the non-file (buffer) bookmarks."
+ bmkp-non-file-alist-only) ; `B S'
+(bmkp-define-show-only-command dired "Display (only) the Dired bookmarks."
+ bmkp-dired-alist-only) ; `M-d M-s'
+(bmkp-define-show-only-command gnus "Display (only) the gnus bookmarks."
+ bmkp-gnus-alist-only) ; `G S'
+(bmkp-define-show-only-command "icicles search-hits" "Display (only) the Icicles search-hits bookmarks."
+ bmkp-icicles-search-hits-alist-only) ; `i S'
+(bmkp-define-show-only-command image "Display (only) the image-file bookmarks."
+ bmkp-image-alist-only) ; `M-I M-S'
+(bmkp-define-show-only-command info "Display (only) the Info bookmarks."
+ bmkp-info-alist-only) ; `I S'
+(bmkp-define-show-only-command desktop "Display (only) the desktop bookmarks."
+ bmkp-desktop-alist-only) ; `K S'
+(bmkp-define-show-only-command man-page "Display (only) the `man' page bookmarks."
+ bmkp-man-alist-only) ; `M S'
+(bmkp-define-show-only-command function "Display (only) the function bookmarks."
+ bmkp-function-alist-only) ; `Q S'
+(bmkp-define-show-only-command region "Display (only) the bookmarks that record a region."
+ bmkp-region-alist-only) ; `R S'
+(bmkp-define-show-only-command tagged "Display (only) the bookmarks that have tags."
+ bmkp-tagged-alist-only) ; `T S'
+(bmkp-define-show-only-command untagged "Display (only) the bookmarks that do not have tags."
+ bmkp-untagged-alist-only) ; Not bound
+(bmkp-define-show-only-command url "Display (only) the url bookmarks."
+ bmkp-url-alist-only) ; `M-u M-s'
+(bmkp-define-show-only-command variable-list "Display (only) the variable-list bookmarks."
+ bmkp-variable-list-alist-only) ; `V S'
+(bmkp-define-show-only-command snippet "Display (only) the snippet bookmarks."
+ bmkp-snippet-alist-only) ; `w S'
+(when (fboundp 'bmkp-eww-bookmark-p) ; Emacs 25+
+ (bmkp-define-show-only-command eww "Display (only) the EWW URL bookmarks."
+ bmkp-eww-alist-only)) ; `W E S'
+(bmkp-define-show-only-command w3m "Display (only) the W3M URL bookmarks."
+ bmkp-w3m-alist-only) ; `W 3 S'
+(bmkp-define-show-only-command temporary "Display (only) the temporary bookmarks."
+ bmkp-temporary-alist-only) ; `X S'
+(bmkp-define-show-only-command bookmark-file "Display (only) the bookmark-file bookmarks."
+ bmkp-bookmark-file-alist-only) ; `Y S'
+(bmkp-define-show-only-command bookmark-list "Display (only) the bookmark-list bookmarks."
+ bmkp-bookmark-list-alist-only) ; `Z S'
+
+;;;###autoload (autoload 'bmkp-bmenu-show-all "bookmark+")
+(defun bmkp-bmenu-show-all () ; Bound to `.' in bookmark list
+ "Show all bookmarks known to the bookmark list (aka \"menu list\").
+Omitted bookmarks are not shown, however.
+Also, this does not revert the bookmark list, to bring it up to date.
+To revert the display from the current list, use `\\<bookmark-bmenu-mode-map>\
+\\[bmkp-bmenu-refresh-menu-list]'.
+To revert the list and display from the bookmark file, use `C-u \\[bmkp-bmenu-refresh-menu-list]'."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (setq bmkp-bmenu-filter-function nil
+ bmkp-bmenu-title "All Bookmarks"
+ bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list)
+ (when (interactive-p) (bmkp-msg-about-sort-order (bmkp-current-sort-order) "All bookmarks are shown")))
+
+;;;###autoload (autoload 'bmkp-bmenu-show-only-autofile-bookmarks "bookmark+")
+(defun bmkp-bmenu-show-only-autofile-bookmarks (&optional arg) ; Bound to `A S' in bookmark list
+ "Display (only) the autofile bookmarks.
+This means bookmarks whose names are the same as the nondirectory part
+of their file names (or their `directory-file-name', for directories).
+
+But with a prefix arg you are prompted for a prefix that each bookmark
+name must have."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (setq bmkp-bmenu-filter-function (if (not arg)
+ 'bmkp-autofile-alist-only
+ (let ((prefix (read-string "Prefix for bookmark names: "
+ nil nil "")))
+ `(lambda () (bmkp-autofile-alist-only ,prefix))))
+ bmkp-bmenu-title "Autofile Bookmarks")
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order) "Only autofile bookmarks are shown")))
+
+;;;###autoload (autoload 'bmkp-bmenu-show-only-file-bookmarks "bookmark+")
+(defun bmkp-bmenu-show-only-file-bookmarks (&optional arg) ; Bound to `F S' in bookmark list
+ "Display a list of file and directory bookmarks (only).
+With a prefix argument, do not include remote files or directories."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (setq bmkp-bmenu-filter-function (if arg 'bmkp-local-file-alist-only 'bmkp-file-alist-only)
+ bmkp-bmenu-title (if arg
+ "Local File and Directory Bookmarks"
+ "File and Directory Bookmarks"))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order) "Only file bookmarks are shown")))
+
+;;;###autoload (autoload 'bmkp-bmenu-show-only-orphaned-local-file-bookmarks "bookmark+")
+(defun bmkp-bmenu-show-only-orphaned-local-file-bookmarks (&optional arg) ; `O S' in bookmark list
+ "Display a list of orphaned local file and directory bookmarks (only).
+With a prefix argument, include remote orphans as well."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (setq bmkp-bmenu-filter-function (if arg
+ 'bmkp-orphaned-file-alist-only
+ 'bmkp-orphaned-local-file-alist-only)
+ bmkp-bmenu-title (if arg
+ "Orphaned File and Directory Bookmarks"
+ "Local Orphaned File and Directory Bookmarks"))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order) "Only orphaned file bookmarks are shown")))
+
+;;;###autoload (autoload 'bmkp-bmenu-show-only-specific-buffer-bookmarks "bookmark+")
+(defun bmkp-bmenu-show-only-specific-buffer-bookmarks (&optional buffer) ; `= b S' in bookmark list
+ "Display (only) the bookmarks for BUFFER.
+Interactively, read the BUFFER name.
+If BUFFER is non-nil, set `bmkp-last-specific-buffer' to it."
+ (interactive (list (bmkp-completing-read-buffer-name)))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (when buffer (setq bmkp-last-specific-buffer buffer))
+ (setq bmkp-bmenu-filter-function 'bmkp-last-specific-buffer-alist-only
+ bmkp-bmenu-title (format "Buffer `%s' Bookmarks" bmkp-last-specific-buffer))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order)
+ (format "Only bookmarks for buffer `%s' are shown"
+ bmkp-last-specific-buffer))))
+
+;;;###autoload (autoload 'bmkp-bmenu-show-only-specific-file-bookmarks "bookmark+")
+(defun bmkp-bmenu-show-only-specific-file-bookmarks (&optional file) ; Bound to `= f S' in bookmark list
+ "Display (only) the bookmarks for FILE, an absolute file name.
+Interactively, read the FILE name.
+If FILE is non-nil, set `bmkp-last-specific-file' to it."
+ (interactive (list (bmkp-completing-read-file-name)))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((orig-last-spec-file bmkp-last-specific-file)
+ (orig-filter-fn bmkp-bmenu-filter-function)
+ (orig-title bmkp-bmenu-title)
+ (orig-latest-alist bmkp-latest-bookmark-alist))
+ (condition-case err
+ (progn
+ (when file (setq bmkp-last-specific-file file))
+ (setq bmkp-bmenu-filter-function 'bmkp-last-specific-file-alist-only
+ bmkp-bmenu-title (format "File `%s' Bookmarks" bmkp-last-specific-file))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function))
+ (bmkp-bmenu-state-file nil)) ; Prevent restoring saved state.
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order)
+ (format "Only bookmarks for file `%s' are shown"
+ bmkp-last-specific-file)))
+ (raise-frame))
+ (error (progn (setq bmkp-last-specific-file orig-last-spec-file
+ bmkp-bmenu-filter-function orig-filter-fn
+ bmkp-bmenu-title orig-title
+ bmkp-latest-bookmark-alist orig-latest-alist)
+ (error "%s" (error-message-string err)))))))
+
+
+;;;###autoload (autoload 'bmkp-bmenu-refresh-menu-list "bookmark+")
+(defun bmkp-bmenu-refresh-menu-list (&optional parg msg-p) ; Bound to `g' in bookmark list
+ "Refresh (revert) the bookmark list display (aka \"menu list\").
+This brings the displayed list up to date with respect to the current
+bookmark list. It does not change the filtering or sorting of the
+displayed list.
+
+With a prefix argument and upon confirmation, refresh the bookmark
+list and its display from the current bookmark file. IOW, it reloads
+the file, overwriting the current bookmark list. This also removes
+any markings and omissions.
+
+You can use command `bmkp-toggle-bookmark-set-refreshes' to toggle
+whether setting a bookmark in any way should automatically refresh the
+list.
+
+From Lisp, non-nil optional arg MSG-P means show progress messages."
+ (interactive "P\np")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((msg "Refreshing from bookmark "))
+ (cond ((and parg (yes-or-no-p (format "Refresh list to bookmarks saved in file `%s'? "
+ bmkp-current-bookmark-file)))
+ (when msg-p (message (setq msg (concat msg "file..."))))
+ (bookmark-load bmkp-current-bookmark-file 'OVERWRITE 'BATCH-NO-SAVE)
+ (setq bmkp-bmenu-marked-bookmarks () ; Start from scratch.
+ bmkp-modified-bookmarks ()
+ bmkp-flagged-bookmarks ()
+ bmkp-bmenu-omitted-bookmarks (condition-case nil
+ (eval (car (get 'bmkp-bmenu-omitted-bookmarks
+ 'saved-value)))
+ (error nil)))
+ (let ((bmkp-bmenu-filter-function nil)) ; Remove any filtering.
+ (bmkp-refresh-menu-list (bookmark-bmenu-bookmark) (not msg-p))))
+ (t
+ (when msg-p (message (setq msg (concat msg "list in memory..."))))
+ (bmkp-refresh-menu-list (bookmark-bmenu-bookmark) (not msg-p))))
+ (when msg-p (message (concat msg "done")))))
+
+;;;###autoload (autoload 'bmkp-bmenu-filter-bookmark-name-incrementally "bookmark+")
+(defun bmkp-bmenu-filter-bookmark-name-incrementally () ; Bound to `P B' in bookmark list
+ "Incrementally filter bookmarks by bookmark name using a regexp."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (unwind-protect
+ (progn (setq bmkp-bmenu-filter-timer
+ (run-with-idle-timer bmkp-incremental-filter-delay 'REPEAT
+ #'bmkp-bmenu-filter-alist-by-bookmark-name-regexp))
+ (bmkp-bmenu-read-filter-input))
+ (bmkp-bmenu-cancel-incremental-filtering)))
+
+(defun bmkp-bmenu-filter-alist-by-bookmark-name-regexp ()
+ "Filter bookmarks by bookmark name, then refresh the bookmark list."
+ (setq bmkp-bmenu-filter-function 'bmkp-regexp-filtered-bookmark-name-alist-only
+ bmkp-bmenu-title (format "Bookmarks with Names Matching Regexp `%s'"
+ bmkp-bmenu-filter-pattern))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp)))
+
+;;;###autoload (autoload 'bmkp-bmenu-filter-file-name-incrementally "bookmark+")
+(defun bmkp-bmenu-filter-file-name-incrementally () ; Bound to `P F' in bookmark list
+ "Incrementally filter bookmarks by file name using a regexp."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (unwind-protect
+ (progn (setq bmkp-bmenu-filter-timer
+ (run-with-idle-timer bmkp-incremental-filter-delay 'REPEAT
+ #'bmkp-bmenu-filter-alist-by-file-name-regexp))
+ (bmkp-bmenu-read-filter-input))
+ (bmkp-bmenu-cancel-incremental-filtering)))
+
+(defun bmkp-bmenu-filter-alist-by-file-name-regexp ()
+ "Filter bookmarks by file name, then refresh the bookmark list."
+ (setq bmkp-bmenu-filter-function 'bmkp-regexp-filtered-file-name-alist-only
+ bmkp-bmenu-title (format "Bookmarks with File Names Matching Regexp `%s'"
+ bmkp-bmenu-filter-pattern))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp)))
+
+;;;###autoload (autoload 'bmkp-bmenu-filter-annotation-incrementally "bookmark+")
+(defun bmkp-bmenu-filter-annotation-incrementally () ; Bound to `P A' in bookmark list
+ "Incrementally filter bookmarks by their annotations using a regexp."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (unwind-protect
+ (progn (setq bmkp-bmenu-filter-timer
+ (run-with-idle-timer bmkp-incremental-filter-delay 'REPEAT
+ #'bmkp-bmenu-filter-alist-by-annotation-regexp))
+ (bmkp-bmenu-read-filter-input))
+ (bmkp-bmenu-cancel-incremental-filtering)))
+
+(defun bmkp-bmenu-filter-alist-by-annotation-regexp ()
+ "Filter bookmarks by annoation, then refresh the bookmark list."
+ (setq bmkp-bmenu-filter-function 'bmkp-regexp-filtered-annotation-alist-only
+ bmkp-bmenu-title (format "Bookmarks with Annotations Matching Regexp `%s'"
+ bmkp-bmenu-filter-pattern))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp)))
+
+;;;###autoload (autoload 'bmkp-bmenu-filter-tags-incrementally "bookmark+")
+(defun bmkp-bmenu-filter-tags-incrementally () ; Bound to `P T' in bookmark list
+ "Incrementally filter bookmarks by tags using a regexp."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (unwind-protect
+ (progn (setq bmkp-bmenu-filter-timer
+ (run-with-idle-timer bmkp-incremental-filter-delay 'REPEAT
+ #'bmkp-bmenu-filter-alist-by-tags-regexp))
+ (bmkp-bmenu-read-filter-input))
+ (bmkp-bmenu-cancel-incremental-filtering)))
+
+(defun bmkp-bmenu-filter-alist-by-tags-regexp ()
+ "Filter bookmarks by tags, then refresh the bookmark list."
+ (setq bmkp-bmenu-filter-function 'bmkp-regexp-filtered-tags-alist-only
+ bmkp-bmenu-title (format "Bookmarks with Tags Matching Regexp `%s'"
+ bmkp-bmenu-filter-pattern))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp)))
+
+(defun bmkp-bmenu-read-filter-input ()
+ "Read input and add it to `bmkp-bmenu-filter-pattern'."
+ (setq bmkp-bmenu-filter-pattern "")
+ (let ((curr-bmk (bookmark-bmenu-bookmark))
+ (orig-title bmkp-bmenu-title)
+ (orig-filt-fn bmkp-bmenu-filter-function)
+ (orig-filt-pat bmkp-bmenu-filter-pattern))
+ (when (eq 'QUIT
+ (let ((tmp-list ())
+ (inhibit-quit t)
+ (prefix-command-echo-keystrokes-functions ()) ; 25+ See Emacs bug #44500.
+ char)
+ (catch 'bmkp-bmenu-read-filter-input
+ (while (condition-case nil
+ (setq char (read-char (concat "Pattern: " bmkp-bmenu-filter-pattern)))
+ ;; `read-char' raises an error for non-char event.
+ (error (throw 'bmkp-bmenu-read-filter-input nil)))
+ (unless (or (not (fboundp 'characterp)) (characterp char)) ; E.g. `M-x', `M-:'
+ (throw 'bmkp-bmenu-read-filter-input nil))
+ (case char
+ ((?\e ?\r) (throw 'bmkp-bmenu-read-filter-input nil)) ; Break and exit.
+ (?\C-g (setq inhibit-quit nil)
+ (throw 'bmkp-bmenu-read-filter-input 'QUIT)) ; Quit.
+ (?\d (or (null tmp-list) ; No-op if no chars to delete.
+ (pop tmp-list)
+ t)) ; Delete last char of `bmkp-bmenu-filter-pattern'.
+ (t (push (text-char-description char) tmp-list))) ; Accumulate CHAR.
+ (setq bmkp-bmenu-filter-pattern (mapconcat #'identity (reverse tmp-list) ""))))))
+ (message "Restoring display prior to incremental filtering...")
+ (setq bmkp-bmenu-title orig-title
+ bmkp-bmenu-filter-function orig-filt-fn
+ bmkp-bmenu-filter-pattern orig-filt-pat)
+ (bookmark-bmenu-list 'FILTEREDP)
+ (bmkp-bmenu-goto-bookmark-named curr-bmk)
+ (message "Restoring display prior to incremental filtering...done"))))
+
+(defun bmkp-bmenu-cancel-incremental-filtering ()
+ "Cancel timer used for incrementally filtering bookmarks."
+ (cancel-timer bmkp-bmenu-filter-timer)
+ (setq bmkp-bmenu-filter-timer nil))
+
+;;;###autoload (autoload 'bmkp-bmenu-toggle-show-only-unmarked "bookmark+")
+(defun bmkp-bmenu-toggle-show-only-unmarked () ; Bound to `<' in bookmark list
+ "Hide all marked bookmarks. Repeat to toggle, showing all."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ ;; Save display, to be sure `bmkp-bmenu-before-hide-marked-alist' is up-to-date.
+ (bmkp-save-menu-list-state)
+ (if (or (bmkp-some-marked-p bmkp-latest-bookmark-alist)
+ (bmkp-some-marked-p bmkp-bmenu-before-hide-marked-alist))
+ (let ((bookmark-alist bmkp-latest-bookmark-alist)
+ status)
+ (if bmkp-bmenu-before-hide-marked-alist
+ (setq bookmark-alist bmkp-bmenu-before-hide-marked-alist
+ bmkp-bmenu-before-hide-marked-alist ()
+ bmkp-latest-bookmark-alist bookmark-alist
+ status 'shown)
+ (setq bmkp-bmenu-before-hide-marked-alist bmkp-latest-bookmark-alist
+ bookmark-alist (bmkp-unmarked-bookmarks-only)
+ bmkp-latest-bookmark-alist bookmark-alist
+ status 'hidden))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (cond ((eq status 'hidden)
+ (bookmark-bmenu-ensure-position)
+ (message "Marked bookmarks are now hidden"))
+ (t
+ (goto-char (point-min))
+ (when (re-search-forward "^>" (point-max) t) (forward-line 0))
+ (message "Marked bookmarks no longer hidden"))))
+ (message "No marked bookmarks to hide"))
+ (when (and (fboundp 'fit-frame-if-one-window)
+ (eq (selected-window) (get-buffer-window (get-buffer-create bmkp-bmenu-buffer) 0)))
+ (fit-frame-if-one-window)))
+
+;;;###autoload (autoload 'bmkp-bmenu-toggle-show-only-marked "bookmark+")
+(defun bmkp-bmenu-toggle-show-only-marked () ; Bound to `>' in bookmark list
+ "Hide all unmarked bookmarks. Repeat to toggle, showing all."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ ;; Save display, to be sure `bmkp-bmenu-before-hide-unmarked-alist' is up-to-date.
+ (bmkp-save-menu-list-state)
+ (if (or (bmkp-some-unmarked-p bmkp-latest-bookmark-alist)
+ (bmkp-some-unmarked-p bmkp-bmenu-before-hide-unmarked-alist))
+ (let ((bookmark-alist bmkp-latest-bookmark-alist)
+ status)
+ (if bmkp-bmenu-before-hide-unmarked-alist
+ (setq bookmark-alist bmkp-bmenu-before-hide-unmarked-alist
+ bmkp-bmenu-before-hide-unmarked-alist ()
+ bmkp-latest-bookmark-alist bookmark-alist
+ status 'shown)
+ (setq bmkp-bmenu-before-hide-unmarked-alist bmkp-latest-bookmark-alist
+ bookmark-alist (bmkp-marked-bookmarks-only)
+ bmkp-latest-bookmark-alist bookmark-alist
+ status 'hidden))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (cond ((eq status 'hidden)
+ (bookmark-bmenu-ensure-position)
+ (message "Unmarked bookmarks are now hidden"))
+ (t
+ (goto-char (point-min))
+ (when (re-search-forward "^>" (point-max) t) (forward-line 0))
+ (message "Unmarked bookmarks no longer hidden"))))
+ (message "No unmarked bookmarks to hide"))
+ (when (and (fboundp 'fit-frame-if-one-window)
+ (eq (selected-window) (get-buffer-window (get-buffer-create bmkp-bmenu-buffer) 0)))
+ (fit-frame-if-one-window)))
+
+
+;;(@* "Menu-List (`*-bmenu-*') Commands Involving Marks")
+;; *** Menu-List (`*-bmenu-*') Commands Involving Marks ***
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-all "bookmark+")
+(defun bmkp-bmenu-mark-all (&optional no-re-sort-p msg-p) ; Bound to `M-m' in bookmark list
+ "Mark all bookmarks, using mark `>'.
+If any bookmark was unmarked before, and if the sort order is marked
+first or last (`s >'), then re-sort.
+
+Non-interactively:
+* Non-nil optional arg NO-RE-SORT-P inhibits re-sorting.
+* Non-nil optional arg MSG-P means display a status message."
+ (interactive "i\np")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((count 0)
+ (nb-marked (length bmkp-bmenu-marked-bookmarks)))
+ (save-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (when msg-p (message "Updating bookmark-list display..."))
+ (while (not (eobp)) (bookmark-bmenu-mark 'NO-RE-SORT-P) (setq count (1+ count))))
+ (unless no-re-sort-p
+ ;; If some were unmarked before, and if sort order is `s >' then re-sort.
+ (when (and (/= nb-marked count) (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk)))))
+ (when msg-p (message "Marked: %d" count))))
+
+;; This is similar to `dired-unmark-all-files'.
+;;;###autoload (autoload 'bmkp-bmenu-unmark-all "bookmark+")
+(defun bmkp-bmenu-unmark-all (mark &optional arg no-re-sort-p msg-p) ; Bound to `M-DEL', `U' in bmk list
+ "Remove a mark from each bookmark.
+Hit the mark character (`>' or `D') to remove those marks,
+ or hit `RET' to remove all marks (both `>' and `D').
+With a prefix arg, you are queried to unmark each marked bookmark.
+Use `\\[help-command]' during querying for help.
+
+If any bookmark was marked before, and if the sort order is marked
+first or last (`s >'), then re-sort.
+
+Non-interactively:
+* MARK is the mark character or a carriage-return character (`?\r').
+* Non-nil ARG (prefix arg) means query.
+* Non-nil optional arg NO-RE-SORT-P inhibits re-sorting.
+* Non-nil optional arg MSG-P means display a status message."
+ (interactive "cRemove marks (RET means all): \nP\ni\np")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (require 'dired-aux)
+ (let* ((count 0)
+ (some-marked-p bmkp-bmenu-marked-bookmarks)
+ (inhibit-read-only t)
+ (case-fold-search nil)
+ (query nil)
+ (string (format "\n%c" mark))
+ (help-form "Type SPC or `y' to unmark one bookmark, DEL or `n' to skip to next,
+`!' to unmark all remaining bookmarks with no more questions."))
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line (if (eq mark ?\r)
+ bmkp-bmenu-header-lines
+ (1- bmkp-bmenu-header-lines))) ; Because STRING starts with a newline.
+ (while (and (not (eobp))
+ (if (eq mark ?\r)
+ (re-search-forward dired-re-mark nil t)
+ (let ((case-fold-search t)) ; Treat `d' the same as `D'.
+ (search-forward string nil t))))
+ (when (or (prog1 (not arg) (when msg-p (message "Updating bookmark-list display...")))
+ (let ((bmk (bookmark-bmenu-bookmark)))
+ (and bmk (dired-query 'query "Unmark bookmark `%s'? " bmk))))
+ (bookmark-bmenu-unmark nil 'NO-RE-SORT-P) (forward-line -1)
+ (setq count (1+ count)))))
+ (unless no-re-sort-p
+ ;; If some were marked before, and if sort order is `s >', then re-sort.
+ (when (and some-marked-p (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk)))))
+ (when msg-p (if (= 1 count) (message "1 mark removed") (message "%d marks removed" count)))))
+
+;;;###autoload (autoload 'bmkp-bmenu-regexp-mark "bookmark+")
+(defun bmkp-bmenu-regexp-mark (regexp &optional no-re-sort-p msg-p) ; Bound to `% m' in bookmark list
+ "Mark bookmarks that match REGEXP.
+The entire bookmark line is tested: bookmark name and possibly file name.
+Note too that if file names are not shown currently then the bookmark
+name is padded at the right with spaces.
+
+If any bookmark was unmarked before, and if the sort order is marked
+first or last (`s >'), then re-sort.
+
+Non-interactively:
+* Non-nil optional arg NO-RE-SORT-P inhibits re-sorting.
+* Non-nil optional arg MSG-P means display a status message."
+ (interactive (list (bmkp-read-regexp "Regexp: ") (prefix-numeric-value current-prefix-arg)))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((count 0)
+ (nb-marked (length bmkp-bmenu-marked-bookmarks)))
+ (save-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (when msg-p (message "Updating bookmark-list display..."))
+ (while (and (not (eobp)) (re-search-forward regexp (point-max) t))
+ (bookmark-bmenu-mark 'NO-RE-SORT-P)
+ (setq count (1+ count))))
+ (unless no-re-sort-p
+ ;; If some were unmarked before, and if sort order is `s >', then re-sort.
+ (when (and (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p))
+ (< nb-marked (length bmkp-bmenu-marked-bookmarks)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk)))))
+ (when msg-p (if (= 1 count) (message "1 bookmark matched") (message "%d bookmarks matched" count)))))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-autofile-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-autofile-bookmarks (&optional arg msgp) ; Bound to `A M' in bookmark list
+ "Mark autofile bookmarks: those whose names are the same as their files.
+With a prefix arg you are prompted for a prefix that each bookmark
+name must have."
+ (interactive "P\np")
+ (if (not arg)
+ (bmkp-bmenu-mark-bookmarks-satisfying #'bmkp-autofile-bookmark-p nil msgp)
+ (let ((prefix (read-string "Prefix for bookmark names: " nil nil "")))
+ (bmkp-bmenu-mark-bookmarks-satisfying
+ #'(lambda (bb) (bmkp-autofile-bookmark-p bb prefix)) nil msgp))))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-autonamed-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-autonamed-bookmarks (&optional msgp) ; Bound to `# M' in bookmark list
+ "Mark autonamed bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying #'bmkp-autonamed-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-bookmark-file-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-bookmark-file-bookmarks (&optional msgp) ; Bound to `Y M' in bookmark list
+ "Mark bookmark-file bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-bookmark-file-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-bookmark-list-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-bookmark-list-bookmarks (&optional msgp) ; Bound to `Z M' in bookmark list
+ "Mark bookmark-list bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-bookmark-list-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-desktop-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-desktop-bookmarks (&optional msgp) ; Bound to `K M' in bookmark list
+ "Mark desktop bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-desktop-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-dired-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-dired-bookmarks (&optional msgp) ; Bound to `M-d M-m' in bookmark list
+ "Mark Dired bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-dired-bookmark-p nil msgp))
+
+(when (fboundp 'bmkp-eww-bookmark-p) ; Emacs 25+
+
+ ;; ;;;###autoload (autoload 'bmkp-bmenu-mark-eww-bookmarks "bookmark+")
+ (defun bmkp-bmenu-mark-eww-bookmarks (&optional msgp) ; Bound to `W E M' in bookmark list
+ "Mark EWW (URL) bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-eww-bookmark-p nil msgp))
+
+ )
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-file-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-file-bookmarks (&optional arg msgp) ; Bound to `F M' in bookmark list
+ "Mark file bookmarks.
+With a prefix argument, do not mark remote files or directories."
+ (interactive "P\np")
+ (bmkp-bmenu-mark-bookmarks-satisfying
+ (if arg 'bmkp-local-file-bookmark-p 'bmkp-file-bookmark-p nil msgp)))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-function-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-function-bookmarks (&optional msgp) ; Bound to `Q M' in bookmark list
+ "Mark function bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying #'bmkp-function-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-gnus-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-gnus-bookmarks (&optional msgp) ; Bound to `G M' in bookmark list
+ "Mark Gnus bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-gnus-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-icicles-search-hits-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-icicles-search-hits-bookmarks (&optional msgp) ; Bound to `i M' in bookmark list
+ "Mark Icicles search-hit bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-icicles-search-hits-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-image-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-image-bookmarks (&optional msgp) ; Bound to `M-I M-M' in bookmark list
+ "Mark image-file bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-image-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-info-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-info-bookmarks (&optional msgp) ; Bound to `I M' in bookmark list
+ "Mark Info bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-info-bookmark-p nil msgp))
+
+(when (featurep 'bookmark+-lit)
+ (defun bmkp-bmenu-mark-lighted-bookmarks (&optional msgp) ; Bound to `H M' in bookmark list
+ "Mark the highlighted bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-lighted-p nil msgp)))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-man-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-man-bookmarks (&optional msgp) ; Bound to `M M' in bookmark list
+ "Mark `man' page bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-man-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-non-file-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-non-file-bookmarks (&optional msgp) ; Bound to `B M' in bookmark list
+ "Mark non-file bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-non-file-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-non-invokable-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-non-invokable-bookmarks (&optional msgp) ; Bound to `N M' in bookmark list
+ "Mark non-invokable bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-non-invokable-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-orphaned-local-file-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-orphaned-local-file-bookmarks (&optional arg msgp) ; Bound to `O M' in bookmark list
+ "Mark orphaned local-file bookmarks (their recorded files are not readable).
+With a prefix argument, mark also remote orphaned files or directories."
+ (interactive "P\np")
+ (bmkp-bmenu-mark-bookmarks-satisfying
+ (if arg 'bmkp-orphaned-file-bookmark-p 'bmkp-orphaned-local-file-bookmark-p nil msgp)))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-region-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-region-bookmarks (&optional msgp) ; Bound to `R M' in bookmark list
+ "Mark bookmarks that record a region."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-region-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-snippet-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-snippet-bookmarks (&optional msgp) ; Bound to `w M' in bookmark list
+ "Mark snippet bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-snippet-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-specific-buffer-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-specific-buffer-bookmarks (&optional buffer msgp) ; `= b M' in bookmark list
+ "Mark bookmarks for BUFFER.
+Interactively, read the name of the buffer.
+If BUFFER is non-nil, set `bmkp-last-specific-buffer' to it."
+ (interactive (list (bmkp-completing-read-buffer-name) t))
+ (when buffer (setq bmkp-last-specific-buffer buffer))
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-last-specific-buffer-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-specific-file-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-specific-file-bookmarks (&optional file msgp) ; Bound to `= f M' in bookmark list
+ "Mark bookmarks for FILE, an absolute file name.
+Interactively, read the file name.
+If FILE is non-nil, set `bmkp-last-specific-file' to it."
+ (interactive (list (bmkp-completing-read-file-name) t))
+ (when file (setq bmkp-last-specific-file file))
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-last-specific-file-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-temporary-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-temporary-bookmarks (&optional msgp) ; Bound to `X M' in bookmark list
+ "Mark temporary bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-temporary-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-variable-list-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-variable-list-bookmarks (&optional msgp) ; Bound to `V M' in bookmark list
+ "Mark variable-list bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-variable-list-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-url-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-url-bookmarks (&optional msgp) ; Bound to `M-u M-m' in bookmark list
+ "Mark URL bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-url-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-w3m-bookmarks "bookmark+")
+(defun bmkp-bmenu-mark-w3m-bookmarks (&optional msgp) ; Bound to `W 3 M' in bookmark list
+ "Mark W3M (URL) bookmarks."
+ (interactive "p")
+ (bmkp-bmenu-mark-bookmarks-satisfying 'bmkp-w3m-bookmark-p nil msgp))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-bookmarks-satisfying "bookmark+")
+(defun bmkp-bmenu-mark-bookmarks-satisfying (pred &optional no-re-sort-p msg-p) ; Not bound
+ "Mark bookmarks that satisfy predicate PRED.
+If you use this interactively, you are responsible for entering a
+symbol that names a unnary predicate. The function you provide is not
+checked - it is simply applied to each bookmark to test it.
+
+If any bookmark was unmarked before, and if the sort order is marked
+first or last (`s >'), then re-sort.
+
+Non-interactively:
+* Non-nil optional arg NO-RE-SORT-P inhibits re-sorting.
+* Non-nil optional arg MSG-P means display a status message."
+ (interactive "aPredicate: \ni\np")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((count 0)
+ (nb-marked (length bmkp-bmenu-marked-bookmarks))
+ bmk)
+ (save-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (when msg-p (message "Updating bookmark-list display..."))
+ (while (not (eobp))
+ (setq bmk (bookmark-bmenu-bookmark))
+ (if (not (funcall pred bmk))
+ (forward-line 1)
+ (bookmark-bmenu-mark 'NO-RE-SORT-P)
+ (setq count (1+ count)))))
+ (unless no-re-sort-p
+ ;; If some were unmarked before, and if sort order is `s >', then re-sort.
+ (when (and (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p))
+ (< nb-marked (length bmkp-bmenu-marked-bookmarks)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk)))))
+ (when msg-p (if (= 1 count) (message "1 bookmark matched") (message "%d bookmarks matched" count)))))
+
+;;;###autoload (autoload 'bmkp-bmenu-toggle-marks "bookmark+")
+(defun bmkp-bmenu-toggle-marks (&optional backup no-re-sort-p msg-p) ; Bound to `t' in bookmark list
+ "Toggle marks: Unmark all marked bookmarks; mark all unmarked bookmarks.
+This affects only the `>' mark, not the `D' flag.
+
+Interactively or with nil optional arg NO-RE-SORT-P, if the current
+sort order is marked first or last (`s >'), then re-sort.
+
+Non-interactively, non-nil optional arg MSG-P means display a status
+message."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((marked-count 0)
+ (unmarked-count 0))
+ (save-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (if (not (bmkp-some-marked-p bmkp-latest-bookmark-alist))
+ (bmkp-bmenu-mark-all no-re-sort-p)
+ (when msg-p (message "Updating bookmark-list display..."))
+ (while (not (eobp))
+ (cond ((bmkp-bookmark-name-member (bookmark-bmenu-bookmark) bmkp-bmenu-marked-bookmarks)
+ (bookmark-bmenu-unmark nil 'NO-RE-SORT-P)
+ (setq unmarked-count (1+ unmarked-count)))
+ (t
+ (bookmark-bmenu-mark 'NO-RE-SORT-P)
+ (setq marked-count (1+ marked-count)))))))
+ ;; If sort order is `s >' then re-sort.
+ (when (and (not no-re-sort-p) (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk))))
+ (when msg-p (message "Marked: %d, unmarked: %d" marked-count unmarked-count))))
+
+;;;###autoload (autoload 'bmkp-bmenu-toggle-marked-temporary/savable "bookmark+")
+(defun bmkp-bmenu-toggle-marked-temporary/savable () ; Bound to `M-X' in bookmark list
+ "Toggle the temporary/savable status of each marked bookmark.
+If none are marked, toggle status of the bookmark of the current line."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((o-str (and (not (bmkp-looking-at-p "^>")) (bookmark-bmenu-bookmark)))
+ (o-point (point))
+ (count-temp 0)
+ (count-save 0)
+ bmk)
+ (message "Toggling temporary status of marked bookmarks...")
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (while (re-search-forward "^>" (point-max) t)
+ (bmkp-toggle-temporary-bookmark (setq bmk (bookmark-bmenu-bookmark)))
+ (if (bmkp-temporary-bookmark-p bmk)
+ (setq count-temp (1+ count-temp))
+ (setq count-save (1+ count-save))))
+ (cond ((and (<= count-temp 0) (<= count-save 0))
+ (if o-str
+ (bmkp-bmenu-goto-bookmark-named o-str)
+ (goto-char o-point)
+ (beginning-of-line))
+ (bmkp-toggle-temporary-bookmark (bookmark-bmenu-bookmark) 'MSG)
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P))
+ (t
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (message "%d made temporary; %d made savable" count-temp count-save)))
+ (if o-str
+ (bmkp-bmenu-goto-bookmark-named o-str)
+ (goto-char o-point)
+ (beginning-of-line)))
+ (when (and (fboundp 'fit-frame-if-one-window)
+ (eq (selected-window) (get-buffer-window (get-buffer-create bmkp-bmenu-buffer) 0)))
+ (fit-frame-if-one-window)))
+
+;;;###autoload (autoload 'bmkp-bmenu-toggle-temporary "bookmark+")
+(defun bmkp-bmenu-toggle-temporary () ; Bound to `C-M-X' in bookmark list
+ "Toggle whether bookmark of current line is temporary (not saved to disk)."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((o-str (bookmark-bmenu-bookmark))
+ (o-point (point)))
+ (bmkp-toggle-temporary-bookmark (bookmark-bmenu-bookmark) 'MSG)
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (if o-str
+ (bmkp-bmenu-goto-bookmark-named o-str)
+ (goto-char o-point)
+ (beginning-of-line))))
+
+;;;###autoload (autoload 'bmkp-bmenu-dired-marked "bookmark+")
+(defun bmkp-bmenu-dired-marked (dirbufname &optional include-omitted-p)
+ ; Bound to `M-d >' in bookmark list
+ "Dired in another window for the marked file and directory bookmarks.
+Absolute file names are used for the entries in the Dired buffer.
+The only entries are for the marked files and directories. These can
+be located anywhere. (In Emacs versions prior to release 23.2, remote
+bookmarks are ignored, because of Emacs bug #5478.)
+
+You are prompted for the Dired buffer name. The `default-directory'
+of the buffer is the same as that of buffer `*Bookmark List*'.
+
+Omitted bookmarks are excluded, by default. With a prefix arg, any
+that are marked are included."
+ (interactive (list (read-string "Dired buffer name: ") current-prefix-arg))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((files ())
+ file)
+ (dolist (bmk (bmkp-sort-omit (bmkp-bmenu-marked-or-this-or-all nil include-omitted-p)))
+ (when (or (bmkp-local-file-bookmark-p bmk)
+ (> emacs-major-version 23)
+ (and (= emacs-major-version 23) (> emacs-minor-version 1)))
+ (setq file (bookmark-get-filename bmk))
+ (unless (file-name-absolute-p file) (setq file (expand-file-name file))) ; Should not happen.
+ (push file files)))
+ (dired-other-window (cons dirbufname files))))
+
+;;;###autoload (autoload 'bmkp-bmenu-delete-marked "bookmark+")
+(defun bmkp-bmenu-delete-marked (&optional no-confirm-p) ; Bound to `D' in bookmark list
+ "Delete all (visible) bookmarks that are marked `>', after confirmation.
+Optional arg NO-CONFIRM-P non-nil means do not ask for confirmation."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-execute-deletions 'MARKED 'NO-CONFIRM))
+
+;;;###autoload (autoload 'bmkp-bmenu-move-marked-to-bookmark-file "bookmark+")
+(defun bmkp-bmenu-move-marked-to-bookmark-file (file &optional duplicates-ok include-omitted-p batchp)
+ ; Bound to `Y > -' in bookmark list
+ "Move the marked bookmarks to bookmark file FILE.
+You are prompted for FILE.
+The marked bookmarks are removed from the current bookmark list and
+appended to those in FILE. If any of them has the same name as a
+bookmark already in FILE then it is renamed by appending a numeric
+suffix \"<N>\" (N=2,3...).
+
+Normally, any of the marked bookmarks that are already present in FILE
+are ignored, rather than duplicating them under a new, suffixed name.
+But if you use a non-negative prefix arg then such duplication is
+allowed.
+
+If no bookmark is marked then move the bookmark of the current line.
+
+Omitted bookmarks are excluded, by default. With a non-positive
+prefix arg, any that are marked are included.
+
+The bookmarks are removed from the currently displayed bookmark list,
+but the bookmark file associated with it is not saved automatically.
+To save it, use \\<bookmark-bmenu-mode-map>`\\[bookmark-bmenu-save]' (as usual).
+
+Non-interactively, non-nil optional arg BATCHP means do not prompt to
+confirm moving to new, empty file if no existing file."
+ (interactive
+ (list (let* ((_IGNORE (bmkp-bmenu-barf-if-not-in-menu-list))
+ (std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ (and (not (bmkp-same-file-p bmkp-current-bookmark-file
+ bookmark-default-file))
+ bookmark-default-file)
+ std-default)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Move marked bookmarks to bookmark file: "
+ (or (and default (file-name-directory default)) "~/")
+ default))
+ (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (<= (prefix-numeric-value current-prefix-arg) 0))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (when (and (not (file-readable-p file))
+ (not batchp)
+ (not (y-or-n-p (format "Move to NEW, EMPTY bookmark file `%s'? " file))))
+ (error "OK - canceled"))
+ (bmkp-bmenu-copy-marked-to-bookmark-file file duplicates-ok include-omitted-p 'MOVE 'BATCH))
+
+;;;###autoload (autoload 'bmkp-bmenu-copy-marked-to-bookmark-file "bookmark+")
+(defun bmkp-bmenu-copy-marked-to-bookmark-file (file &optional duplicates-ok include-omitted-p movep batchp)
+ ; Bound to `Y > +' in bookmark list
+ "Copy the marked bookmarks to bookmark file FILE.
+You are prompted for FILE.
+The marked bookmarks are appended to those already in FILE.
+If any of them has the same name as a bookmark already in FILE then it
+is renamed by appending a numeric suffix \"<N>\" (N=2,3...).
+
+Normally, any of the marked bookmarks that are already present in FILE
+are ignored, rather than duplicating them under a new, suffixed name.
+But if you use a non-negative prefix arg then such duplication is
+allowed. Use this, for example, to duplicate a bookmark in the
+current bookmark file (use that file as FILE).
+
+If no bookmark is marked then copy the bookmark of the current line.
+
+Omitted bookmarks are excluded, by default. With a non-positive
+prefix arg, any that are marked are included.
+
+Non-interactively:
+* Non-nil MOVEP means delete the bookmarks copied.
+* Non-nil BATCHP means do not prompt to confirm moving to a new, empty
+ file if there is no existing file."
+ (interactive
+ (list (let* ((_IGNORE (bmkp-bmenu-barf-if-not-in-menu-list))
+ (std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ (and (not (bmkp-same-file-p bmkp-current-bookmark-file
+ bookmark-default-file))
+ bookmark-default-file)
+ std-default)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Copy marked bookmarks to bookmark file: "
+ (or (and default (file-name-directory default)) "~/")
+ default))
+ (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (<= (prefix-numeric-value current-prefix-arg) 0))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (when (file-directory-p file) (error "`%s' is a directory, not a file" file))
+ (when (and (not (file-readable-p file))
+ (not batchp)
+ (not (y-or-n-p (format "Copy to NEW, EMPTY bookmark file `%s'? " file))))
+ (error "OK - canceled"))
+ (let ((bookmark-save-flag nil) ; Inhibit auto-saving for the duration.
+ imported)
+ (let ((marked-bmks (bmkp-sort-omit
+ (bmkp-bmenu-marked-or-this-or-all nil include-omitted-p)))
+ (bookmark-alist bookmark-alist)
+ (bookmark-alist-modification-count bookmark-alist-modification-count))
+ (when (and (not (zerop bookmark-alist-modification-count)) ; Unsaved changes.
+ (yes-or-no-p "Unsaved changes. Save bookmarks before copying? "))
+ (bookmark-save))
+ (with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
+ (goto-char (point-min))
+ (if (file-exists-p file)
+ (bookmark-maybe-upgrade-file-format)
+ (delete-region (point-min) (point-max)) ; In case a find-file hook inserted a header etc.
+ (if (boundp 'bookmark-file-coding-system) ; Insert timestamp and an empty bookmark list.
+ (bookmark-insert-file-format-version-stamp bookmark-file-coding-system) ; Emacs 25.2+
+ (bookmark-insert-file-format-version-stamp))
+ (insert "(\n)"))
+ (let ((blist (bookmark-alist-from-buffer)))
+ (unless (listp blist) (error "Invalid bookmark list in file `%s'" file))
+ (setq bookmark-alist blist) ; Bookmarks in FILE
+ (setq imported (bookmark-import-new-list marked-bmks duplicates-ok 'RETURN-BMKS))
+ (if (and (zerop (nth 0 imported)) (zerop (nth 1 imported)))
+ (unless batchp (message "No changes"))
+ (unless batchp (message "%d added, %d renamed" (nth 1 imported) (nth 0 imported)))
+ (bookmark-write-file file)))))
+ ;; (Exit `let', to restore `bookmark-alist'.)
+ (cond (movep
+ ;; Moved. Delete moved bookmarks. Refresh from memory w/o asking.
+ (dolist (bmk (nth 2 imported)) (bookmark-delete bmk 'BATCHP))
+ (bmkp-bmenu-refresh-menu-list nil 'MSGP))
+ ((not (zerop (nth 0 imported)))
+ ;; Copied, and some were renamed. Refresh from file w/o asking.
+ (bookmark-load bmkp-current-bookmark-file 'OVERWRITE 'BATCH-NO-SAVE)
+ (bmkp-refresh-menu-list (bookmark-bmenu-bookmark))))))
+
+;;;###autoload (autoload 'bmkp-bmenu-create-bookmark-file-from-marked "bookmark+")
+(defun bmkp-bmenu-create-bookmark-file-from-marked (file create-b-f-bookmark-p
+ &optional include-omitted-p batchp)
+ ; Bound to `Y > 0' in bookmark list
+ "Create bookmark file FILE by copying the marked bookmarks.
+You are prompted for FILE.
+They are not deleted from the current bookmark file. To delete them, use \
+\\<bookmark-bmenu-mode-map>`\\[bmkp-bmenu-delete-marked]'.
+
+With a non-negative prefix arg, create also a bookmark-file bookmark
+for FILE. You are prompted for the bookmark name.
+
+If no bookmark is marked then copy the bookmark of the current line.
+
+Omitted bookmarks are excluded, by default. With a non-positive
+prefix arg, any that are marked are included.
+
+Non-interactively, non-nil optional arg BATCHP means do not prompt to
+confirm moving to new, empty file if no existing file."
+ (interactive
+ (list (let* ((_IGNORE (bmkp-bmenu-barf-if-not-in-menu-list))
+ (std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ (and (not (bmkp-same-file-p bmkp-current-bookmark-file
+ bookmark-default-file))
+ bookmark-default-file)
+ std-default)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Create bookmark file from marked: "
+ (or (and default (file-name-directory default)) "~/")
+ default))
+ (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (<= (prefix-numeric-value current-prefix-arg) 0))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (when (and (file-readable-p file)
+ (not (file-directory-p file))
+ (not batchp)
+ (not (y-or-n-p (format "File `%s' already exists. Overwrite? " file))))
+ (error "OK - canceled"))
+ (bmkp-empty-file file)
+ (bmkp-bmenu-copy-marked-to-bookmark-file file nil include-omitted-p nil 'BATCH)
+ (when create-b-f-bookmark-p (bmkp-set-bookmark-file-bookmark file)))
+
+;;;###autoload (autoload 'bmkp-bmenu-set-bookmark-file-bookmark-from-marked "bookmark+")
+(defun bmkp-bmenu-set-bookmark-file-bookmark-from-marked (file &optional include-omitted-p batchp)
+ ; Same as `C-u Y > 0' in bookmark list (but not bound).
+ "Set a bookmark-file bookmark for the marked bookmarks.
+You are prompted for the names of the new bookmark file and the
+bookmark-file bookmark.
+
+This is the same as using a non-negative prefix arg with
+`bmkp-bmenu-create-bookmark-file-from-marked'.
+
+If no bookmark is marked then use the bookmark of the current line.
+
+Omitted bookmarks are excluded, by default. With a prefix arg, any
+that are marked are included.
+
+Non-interactively, non-nil optional arg BATCHP means do not prompt to
+confirm moving to new, empty file if no existing file."
+ (interactive
+ (list (let* ((_IGNORE (bmkp-bmenu-barf-if-not-in-menu-list))
+ (std-default (bmkp-default-bookmark-file))
+ (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
+ (and (not (bmkp-same-file-p bmkp-current-bookmark-file
+ bookmark-default-file))
+ bookmark-default-file)
+ std-default)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Create a bookmark file from marked: "
+ (or (and default (file-name-directory default)) "~/")
+ default))
+ current-prefix-arg))
+ (bmkp-bmenu-create-bookmark-file-from-marked file 'CREATE-B-F-BMK include-omitted-p batchp))
+
+;;;###autoload (autoload 'bmkp-bmenu-load-marked-bookmark-file-bookmarks "bookmark+")
+(defun bmkp-bmenu-load-marked-bookmark-file-bookmarks (&optional msg-p) ; Bound to `M-l' in bookmark list
+ "Load the bookmark-file bookmarks that are marked, in display order.
+Non bookmark-file bookmarks that are marked are ignored.
+You can sort the bookmark-list display to change the load order.
+
+NOTE: Automatically saving the current bookmark list is turned OFF
+before loading, and it remains turned off until you explicitly turn it
+back on. Bookmark+ does not assume that you want to automatically
+save all of the newly loaded bookmarks in the same bookmark file. If
+you do, just use \\<bookmark-bmenu-mode-map>`\\[bmkp-toggle-saving-bookmark-file]' \
+to turn saving back on."
+ (interactive "p")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((bmks (bmkp-remove-if-not #'bmkp-bookmark-file-bookmark-p
+ (bmkp-remove-if-not 'bmkp-marked-bookmark-p bmkp-sorted-alist)))
+ (bmk (bookmark-bmenu-bookmark)))
+ (unless bmks (error "No marked bookmark-file bookmarks"))
+ ;; Maybe save bookmarks first.
+ (when (or (not msg-p)
+ (and (> bookmark-alist-modification-count 0)
+ (condition-case err
+ (yes-or-no-p "Save current bookmarks? (`C-g': cancel load too) ")
+ (quit (error "OK - canceled"))
+ (error (error (error-message-string err))))))
+ (bookmark-save))
+ (when (or (not msg-p)
+ (yes-or-no-p "Load the marked bookmark-file bookmarks? ")
+ (error "OK - canceled"))
+ (when bookmark-save-flag ; Turn off autosaving.
+ (bmkp-toggle-saving-bookmark-file) ; No MSG-P arg - issue message below.
+ (when bookmark-save-flag (setq bookmark-save-flag nil)) ; Be sure it's off.
+ (when msg-p (message "Autosaving of current bookmark file is now OFF")))
+ (when msg-p (message "Loading marked bookmark files..."))
+ (dolist (bmk bmks) ; Load.
+ ;; USE BATCHP: Do not refresh list or display messages here - do that after iterate.
+ (bookmark-load (bookmark-get-filename bmk) nil 'BATCHP))
+ ;; $$$$$$ Should we do (bmkp-tags-list) here to update the tags cache?
+ (bmkp-refresh-menu-list bmk (not msg-p)) ; Refresh after iterate.
+ (when msg-p (message "Autosaving is now OFF. Loaded: %s"
+ (mapconcat (lambda (bmk) (format "`%s'" (bmkp-bookmark-name-from-record bmk)))
+ bmks
+ ", "))))))
+
+;;;###autoload (autoload 'bmkp-bmenu-load-marking "bookmark+")
+(defun bmkp-bmenu-load-marking (file &optional unmark-first-p)
+ "Like `bookmark-load', but mark the bookmarks that are loaded.
+With a prefix arg, unmark all bookmarks first."
+ (interactive
+ (list (let ((default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (bmkp-default-bookmark-file)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Add bookmarks from file: "
+ (or (file-name-directory default) "~/")
+ default
+ t))
+ current-prefix-arg))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (when unmark-first-p (bmkp-bmenu-unmark-all ?\r))
+ (let* ((bmkp-read-bookmark-file-hook bmkp-read-bookmark-file-hook)
+ (bmks-read (bookmark-load file)))
+ (bmkp-bmenu-mark-bookmarks-satisfying
+ `(lambda (bmk) (bmkp-get-bookmark-in-alist bmk t ',bmks-read)))
+ bmks-read)) ; Return list of bookmarks read.
+
+;;;###autoload (autoload 'bmkp-bmenu-load-marking-unmark-first "bookmark+")
+(defun bmkp-bmenu-load-marking-unmark-first (file)
+ "Like `bmkp-bmenu-load-marking' with a prefix arg: unmark all first."
+ (interactive
+ (list (let ((default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
+ (bmkp-default-bookmark-file)
+ bmkp-last-bookmark-file)))
+ (bmkp-read-bookmark-file-name "Add bookmarks from file: "
+ (or (file-name-directory default) "~/")
+ default
+ t))))
+ (bmkp-bmenu-load-marking file t))
+
+;;;###autoload (autoload 'bmkp-bmenu-make-sequence-from-marked "bookmark+")
+(defun bmkp-bmenu-make-sequence-from-marked (seqname &optional dont-omit-p) ; Not bound
+ "Create or update a sequence bookmark from the visible marked bookmarks.
+The bookmarks that are currently marked are recorded as a sequence, in
+their current order in buffer `*Bookmark List*'.
+When you \"jump\" to the sequence bookmark, the bookmarks in the
+sequence are processed in order.
+
+By default, omit the marked bookmarks, after creating the sequence.
+With a prefix arg, do not omit them.
+
+If a bookmark with the specified name already exists, it is
+overwritten. If a sequence bookmark with the name already exists,
+then you are prompted whether to add the marked bookmarks to the
+beginning of the existing sequence (or simply replace it).
+
+Note that another existing sequence bookmark can be marked, and thus
+included in the sequence bookmark created or updated. That is, you
+can include other sequences within a sequence bookmark.
+
+Returns the bookmark (internal record) created or updated."
+ (interactive "sName of sequence bookmark: \nP")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((marked-bmks ())
+ (count 0))
+ (message "Making sequence from marked bookmarks...")
+ (save-excursion (with-current-buffer bmkp-bmenu-buffer
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (while (re-search-forward "^>" (point-max) t)
+ (push (bookmark-bmenu-bookmark) marked-bmks)
+ (setq count (1+ count)))))
+ (when (zerop count) (error "No marked bookmarks"))
+ (bmkp-set-sequence-bookmark seqname (nreverse marked-bmks)))
+ (let ((new (bmkp-get-bookmark seqname 'NOERROR)))
+ (unless (memq new bmkp-latest-bookmark-alist)
+ (setq bmkp-latest-bookmark-alist (cons new bmkp-latest-bookmark-alist)))
+ (unless dont-omit-p
+ (bmkp-bmenu-omit-marked)
+ (message (substitute-command-keys "Marked bookmarks now OMITTED - use \
+\\<bookmark-bmenu-mode-map>`\\[bmkp-bmenu-show-only-omitted-bookmarks]' to show")))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (bmkp-bmenu-goto-bookmark-named seqname)
+ new))
+
+
+;;(@* "Omitted Bookmarks")
+;; *** Omitted Bookmarks ***
+
+;;;###autoload (autoload 'bmkp-bmenu-omit "bookmark+")
+(defun bmkp-bmenu-omit () ; Not bound
+ "Omit this bookmark."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (push (bookmark-bmenu-bookmark) bmkp-bmenu-omitted-bookmarks)
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (message "Omitted 1 bookmark"))
+
+;;;###autoload (autoload 'bmkp-bmenu-omit/unomit-marked "bookmark+")
+(defun bmkp-bmenu-omit/unomit-marked () ; Bound to `- >' in bookmark list
+ "Omit all marked bookmarks or, if showing only omitted ones, unomit."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (if (eq bmkp-bmenu-filter-function 'bmkp-omitted-alist-only)
+ (bmkp-bmenu-unomit-marked)
+ (bmkp-bmenu-omit-marked)))
+
+;;;###autoload (autoload 'bmkp-bmenu-omit-marked "bookmark+")
+(defun bmkp-bmenu-omit-marked () ; Bound to `- >' in bookmark list
+ "Omit all marked bookmarks.
+They will henceforth be invisible to the bookmark list.
+You can, however, use \\<bookmark-bmenu-mode-map>`\\[bmkp-bmenu-show-only-omitted-bookmarks]' \
+to see them.
+You can then mark some of them and use `\\[bmkp-bmenu-omit/unomit-marked]' to make those marked
+ available again for the bookmark list."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((o-str (and (not (bmkp-looking-at-p "^>")) (bookmark-bmenu-bookmark)))
+ (o-point (point))
+ (count 0))
+ (message "Omitting marked bookmarks...")
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (while (re-search-forward "^>" (point-max) t)
+ (setq bmkp-bmenu-omitted-bookmarks (cons (bookmark-bmenu-bookmark) bmkp-bmenu-omitted-bookmarks)
+ count (1+ count)))
+ (if (<= count 0)
+ (message "No marked bookmarks")
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (message "Omitted %d bookmarks" count))
+ (if o-str
+ (bmkp-bmenu-goto-bookmark-named o-str)
+ (goto-char o-point)
+ (beginning-of-line)))
+ (when (and (fboundp 'fit-frame-if-one-window)
+ (eq (selected-window) (get-buffer-window (get-buffer-create bmkp-bmenu-buffer) 0)))
+ (fit-frame-if-one-window)))
+
+;;;###autoload (autoload 'bmkp-bmenu-unomit-marked "bookmark+")
+(defun bmkp-bmenu-unomit-marked () ; `- >' in bookmark list when showing omitted bookmarks
+ "Remove all marked bookmarks from the list of omitted bookmarks.
+They will henceforth be available for display in the bookmark list.
+\(In order to see and then mark omitted bookmarks you must use \\<bookmark-bmenu-mode-map>\
+`\\[bmkp-bmenu-show-only-omitted-bookmarks]'.)"
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (unless bmkp-bmenu-omitted-bookmarks (error "No omitted bookmarks to UN-omit"))
+ (unless (eq bmkp-bmenu-filter-function 'bmkp-omitted-alist-only)
+ (error "You must use command `bmkp-bmenu-show-only-omitted-bookmarks' first"))
+ (let ((count 0))
+ (message "UN-omitting marked bookmarks...")
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (while (re-search-forward "^>" (point-max) t)
+ (let ((bmk-name (bookmark-bmenu-bookmark)))
+ (when (bmkp-bookmark-name-member bmk-name bmkp-bmenu-omitted-bookmarks)
+ (setq bmkp-bmenu-omitted-bookmarks (bmkp-delete-bookmark-name-from-list
+ bmk-name bmkp-bmenu-omitted-bookmarks)
+ count (1+ count)))))
+ (if (<= count 0)
+ (message "No marked bookmarks")
+ (setq bmkp-bmenu-filter-function nil
+ bmkp-bmenu-title "All Bookmarks"
+ bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (message "UN-omitted %d bookmarks" count)))
+ (when (and (fboundp 'fit-frame-if-one-window)
+ (eq (selected-window) (get-buffer-window (get-buffer-create bmkp-bmenu-buffer) 0)))
+ (fit-frame-if-one-window)))
+
+;;;###autoload (autoload 'bmkp-bmenu-show-only-omitted-bookmarks "bookmark+")
+(defun bmkp-bmenu-show-only-omitted-bookmarks () ; Bound to `- S' in bookmark list to show only omitted
+ "Show only the omitted bookmarks.
+You can then mark some of them and use `\\<bookmark-bmenu-mode-map>\\[bmkp-bmenu-omit/unomit-marked]' to
+ make those that are marked available again for the bookmark list."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (unless bmkp-bmenu-omitted-bookmarks (error "No omitted bookmarks")) ; Cannot use macro for this.
+ (setq bmkp-bmenu-filter-function 'bmkp-omitted-alist-only
+ bmkp-bmenu-title "Omitted Bookmarks")
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order) "Only omitted bookmarks are shown now")))
+
+
+;;(@* "Search-and-Replace Locations of Marked Bookmarks")
+;; *** Search-and-Replace Locations of Marked Bookmarks ***
+
+(when (> emacs-major-version 22)
+ (defun bmkp-bmenu-isearch-marked-bookmarks (&optional allp include-omitted-p)
+ ; Bound to `M-s a C-s' in bookmark list
+ "Isearch the marked bookmark locations, in their current order.
+If no bookmark is marked, search the bookmark of the current line.
+
+With a non-negative prefix arg, search all bookmarks.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included."
+ (interactive (list (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((bookmarks (mapcar #'car (bmkp-sort-omit
+ (bmkp-bmenu-marked-or-this-or-all allp include-omitted-p))))
+ (bmkp-use-region nil)) ; Suppress region handling.
+ (bmkp-isearch-bookmarks bookmarks))) ; Defined in `bookmark+-1.el'.
+
+ (defun bmkp-bmenu-isearch-marked-bookmarks-regexp (&optional allp include-omitted-p)
+ ; `M-s a M-C-s' in bookmark list
+ "Regexp Isearch the marked bookmark locations, in their current order.
+If no bookmark is marked, search the bookmark of the current line.
+
+With a non-negative prefix arg, search all bookmarks.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included."
+ (interactive (list (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((bookmarks (mapcar #'car (bmkp-sort-omit
+ (bmkp-bmenu-marked-or-this-or-all allp include-omitted-p))))
+ (bmkp-use-region nil)) ; Suppress region handling.
+ (bmkp-isearch-bookmarks-regexp bookmarks)))) ; Defined in `bookmark+-1.el'.
+
+;;;###autoload (autoload 'bmkp-bmenu-search-marked-bookmarks-regexp "bookmark+")
+(defun bmkp-bmenu-search-marked-bookmarks-regexp (regexp &optional allp include-omitted-p)
+ ; `M-s a M-s' in bookmark list
+ "Search the marked file bookmarks, in their current order, for REGEXP.
+Use `\\[tags-loop-continue]' to advance among the search hits.
+Marked directory and non-file bookmarks are ignored.
+
+If no bookmark is marked, search the bookmark of the current line.
+
+With a non-negative prefix arg, search all bookmarks.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included."
+ (interactive (list (bmkp-read-regexp "Search marked file bookmarks (regexp): ")
+ (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (tags-search regexp '(let ((files ())
+ file)
+ (dolist (bmk (bmkp-sort-omit
+ (bmkp-bmenu-marked-or-this-or-all allp include-omitted-p)))
+ (setq file (bookmark-get-filename bmk))
+ (when (and (not (equal bmkp-non-file-filename file))
+ (not (file-directory-p file)))
+ (push file files)))
+ (setq files (nreverse files)))))
+
+;;;###autoload (autoload 'bmkp-bmenu-query-replace-marked-bookmarks-regexp "bookmark+")
+(defun bmkp-bmenu-query-replace-marked-bookmarks-regexp (from to ; Bound to `M-q' in bookmark list
+ &optional delimited include-omitted-p)
+ "`query-replace-regexp' FROM with TO, for all marked file bookmarks.
+If you exit (`\\[keyboard-quit]', `RET' or `q'), you can use `\\[tags-loop-continue]' to resume where
+you left off.
+
+If no bookmark is marked, act on the bookmark of the current line.
+
+A non-negative prefix arg means replace only word-delimited matches.
+
+Omitted bookmarks are excluded, by default. With a non-positive
+prefix arg, any that are marked are included."
+ (interactive (let ((common (query-replace-read-args "Query replace regexp in marked files" t t)))
+ (list (nth 0 common)
+ (nth 1 common)
+ (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (<= (prefix-numeric-value current-prefix-arg) 0)))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (tags-query-replace from to delimited
+ '(let ((files ())
+ file)
+ (dolist (bmk (bmkp-sort-omit
+ (bmkp-bmenu-marked-or-this-or-all nil include-omitted-p)))
+ (setq file (bookmark-get-filename bmk))
+ (let ((buffer (get-file-buffer file)))
+ (when (and buffer (with-current-buffer buffer buffer-read-only))
+ (error "File `%s' is visited read-only" file)))
+ (when (and (not (equal bmkp-non-file-filename file))
+ (not (file-directory-p file)))
+ (push file files)))
+ (setq files (nreverse files)))))
+
+
+;;(@* "Tags")
+;; *** Tags ***
+
+;; Not bound, but `T 0' is `bmkp-remove-all-tags'.
+;;;###autoload (autoload 'bmkp-bmenu-remove-all-tags "bookmark+")
+(defun bmkp-bmenu-remove-all-tags (&optional must-confirm-p)
+ "Remove all tags from this bookmark.
+Interactively, you are required to confirm."
+ (interactive "p")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((bookmark (bookmark-bmenu-bookmark)))
+ (when (and must-confirm-p (null (bmkp-get-tags bookmark)))
+ (error "Bookmark has no tags to remove"))
+ (when (or (not must-confirm-p) (y-or-n-p "Remove all tags from this bookmark? "))
+ (bmkp-remove-all-tags bookmark))))
+
+;;;###autoload (autoload 'bmkp-bmenu-add-tags "bookmark+")
+(defun bmkp-bmenu-add-tags () ; Only on `mouse-3' menu in bookmark list.
+ "Add some tags to this bookmark."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((nb-added (bmkp-add-tags (bookmark-bmenu-bookmark) (bmkp-read-tags-completing))))
+ (when (and (< nb-added 0) ; It was untagged but is now tagged. If `s t' then re-sort.
+ (equal bmkp-sort-comparer '((bmkp-tagged-cp) bmkp-alpha-p))) ; Hardcoded value, for now.
+ (bmkp-bmenu-sort-tagged-before-untagged))
+ nb-added))
+
+;;;###autoload (autoload 'bmkp-bmenu-set-tag-value "bookmark+")
+(defun bmkp-bmenu-set-tag-value () ; Bound to `T v' in bookmark list
+ "Set the value of one of this bookmark's tags."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((this-bmk (bookmark-bmenu-bookmark)))
+ (bmkp-set-tag-value
+ this-bmk
+ (bmkp-read-tag-completing "Tag: " (mapcar 'bmkp-full-tag (bmkp-get-tags this-bmk)))
+ (read (read-string "Value: "))
+ nil
+ 'MSG)))
+
+;;;###autoload (autoload 'bmkp-bmenu-set-tag-value-for-marked "bookmark+")
+(defun bmkp-bmenu-set-tag-value-for-marked (tag value &optional allp include-omitted-p msg-p)
+ ; Bound to `T > v' in bookmark list
+ "Set the value of TAG to VALUE, for each of the marked bookmarks.
+If any of the bookmarks has no tag named TAG, then add one with VALUE.
+
+If no bookmark is marked, act on the bookmark of the current line.
+
+With a non-negative prefix arg, act on all bookmarks.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included.
+
+Non-interactively, non-nil MSG-P means display messages."
+ (interactive (list (bmkp-read-tag-completing)
+ (read (read-string "Value: "))
+ (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))
+ 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (when msg-p (message "Setting tag values..."))
+ (let ((marked (bmkp-bmenu-marked-or-this-or-all allp include-omitted-p)))
+ (unless marked (error "No marked bookmarks"))
+ (when msg-p (message "Setting tag values..."))
+ (bmkp-set-tag-value-for-bookmarks marked tag value))
+ (when (and msg-p tag) (message "Setting tag values...done")))
+
+;;;###autoload (autoload 'bmkp-bmenu-remove-tags "bookmark+")
+(defun bmkp-bmenu-remove-tags (&optional msg-p) ; Only on `mouse-3' menu in bookmark list.
+ "Remove some tags from this bookmark.
+Non-interactively, non-nil MSG-P means display messages."
+ (interactive "p")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let* ((bmk (bookmark-bmenu-bookmark))
+ (nb-removed (bmkp-remove-tags bmk
+ (bmkp-read-tags-completing
+ (mapcar 'bmkp-full-tag (bmkp-get-tags bmk)) t)
+ nil
+ msg-p)))
+ (when (and (< nb-removed 0) ; It was tagged but is now untagged. If `s t' then re-sort.
+ (equal bmkp-sort-comparer '((bmkp-tagged-cp) bmkp-alpha-p))) ; Hardcoded value, for now.
+ (bmkp-bmenu-sort-tagged-before-untagged))
+ nb-removed))
+
+;;;###autoload (autoload 'bmkp-bmenu-add-tags-to-marked "bookmark+")
+(defun bmkp-bmenu-add-tags-to-marked (tags &optional allp include-omitted-p msg-p)
+ ; Bound to `T > +' in bookmark list
+ "Add TAGS to each of the marked bookmarks.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter each tag, but you are not limited to
+choosing existing tags.
+
+If no bookmark is marked, act on the bookmark of the current line.
+
+With a non-negative prefix arg, act on all bookmarks.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included.
+
+Non-interactively:
+ TAGS is a list of strings.
+ Non-nil MSG-P means display messages."
+ (interactive (list (bmkp-read-tags-completing)
+ (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))
+ 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((marked (bmkp-bmenu-marked-or-this-or-all allp include-omitted-p))
+ (curr-bmk (bookmark-bmenu-bookmark))
+ (some-were-untagged-p nil))
+ (unless marked (error "No marked bookmarks"))
+ (when msg-p (message "Adding tags..."))
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bmk (mapcar #'car marked))
+ (when (< (bmkp-add-tags bmk tags 'NO-UPDATE-P) 0) (setq some-were-untagged-p t))))
+ (bmkp-tags-list) ; Update the tags cache now, after iterate.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh-menu-list curr-bmk (not msg-p)) ; Refresh after iterate.
+ (when (and some-were-untagged-p (equal bmkp-sort-comparer '((bmkp-tagged-cp) bmkp-alpha-p)))
+ (bmkp-bmenu-sort-tagged-before-untagged))
+ (when (and msg-p tags) (message "Tags added: %S" tags))))
+
+;;;###autoload (autoload 'bmkp-bmenu-remove-tags-from-marked "bookmark+")
+(defun bmkp-bmenu-remove-tags-from-marked (tags &optional allp include-omitted-p msg-p)
+ ; Bound to `T > -' in bookmark list
+ "Remove TAGS from each of the marked bookmarks.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter each tag.
+
+If no bookmark is marked, act on the bookmark of the current line.
+
+With a non-negative prefix arg, act on all bookmarks.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included.
+
+Non-interactively, non-nil MSG-P means display messages."
+ (interactive
+ (let ((tgs ())
+ (all (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0)))
+ (omt (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))))
+
+ (dolist (bmk (bmkp-bmenu-marked-or-this-or-all all omt))
+ (setq tgs (bmkp-set-union tgs (bmkp-get-tags bmk))))
+ (unless tgs (error "No tags to remove"))
+ (list (bmkp-read-tags-completing tgs t) all omt 'MSG)))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((marked (if allp
+ bookmark-alist
+ (or (if include-omitted-p
+ (bmkp-marked-bookmarks-only)
+ (bmkp-remove-if #'bmkp-omitted-bookmark-p (bmkp-marked-bookmarks-only)))
+ (and (bookmark-bmenu-bookmark)
+ (list (bmkp-get-bookmark (bookmark-bmenu-bookmark)))))))
+ (curr-bmk (bookmark-bmenu-bookmark))
+ (some-are-now-untagged-p nil))
+ (unless marked (error "No marked bookmarks"))
+ (when msg-p (message "Removing tags..."))
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bmk (mapcar #'car marked))
+ (when (< (bmkp-remove-tags bmk tags 'NO-UPDATE-P) 0) (setq some-are-now-untagged-p t))))
+ (bmkp-tags-list) ; Update the tags cache now, after iterate.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh-menu-list curr-bmk (not msg-p)) ; Refresh after iterate.
+ (when (and some-are-now-untagged-p (equal bmkp-sort-comparer '((bmkp-tagged-cp) bmkp-alpha-p)))
+ (bmkp-bmenu-sort-tagged-before-untagged))
+ (when (and msg-p tags) (message "Tags removed: %S" tags))))
+
+;;;###autoload (autoload 'bmkp-bmenu-list-tags-of-marked "bookmark+")
+(defun bmkp-bmenu-list-tags-of-marked (fullp &optional msg-p)
+ ; Bound to `T > l' in bookmark list
+ "List the tags used in the marked bookmarks.
+Show the list in the minibuffer or, if not enough space, in buffer
+`*All Tags*'. The tags are listed alphabetically, respecting option
+`case-fold-search'.
+
+With no prefix arg, list only the tag names. With a prefix arg, list
+the full alist of tags. Note that when the full tags alist is shown,
+the same tag name appears once for each of its different values.
+
+Non-interactively, non-nil MSG-P means display a status message."
+ (interactive "P\np")
+ (require 'pp)
+ (when msg-p (message "Gathering tags..."))
+ (pp-display-expression (sort (let ((bookmark-alist (bmkp-marked-bookmarks-only))
+ bmkp-tags-alist) ; Prevent updating it.
+ (bmkp-tags-list (not fullp) t))
+ (if fullp
+ (lambda (t1 t2) (bmkp-string-less-case-fold-p (car t1) (car t2)))
+ 'bmkp-string-less-case-fold-p))
+ "*Tags of Marked Bookmarks*"))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-bookmarks-tagged-regexp "bookmark+")
+(defun bmkp-bmenu-mark-bookmarks-tagged-regexp (regexp &optional notp no-re-sort-p msg-p)
+ ; `T m %' in bookmark list
+ "Mark bookmarks any of whose tags match REGEXP.
+With a prefix arg, mark all that are tagged but have no matching tags.
+
+If any bookmark was unmarked before, and if the sort order is marked
+first or last (`s >'), then re-sort.
+
+Non-interactively:
+* Non-nil NOTP: see prefix arg, above.
+* Non-nil optional arg NO-RE-SORT-P inhibits re-sorting.
+* Non-nil optional arg MSG-P means display a status message."
+ (interactive (list (bmkp-read-regexp "Regexp: ") current-prefix-arg nil
+ (prefix-numeric-value current-prefix-arg)))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((count 0)
+ (nb-marked (length bmkp-bmenu-marked-bookmarks))
+ tags anyp)
+ (save-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (when msg-p (message "Updating bookmark-list display..."))
+ (while (not (eobp))
+ (setq tags (bmkp-get-tags (bookmark-bmenu-bookmark))
+ anyp (and tags (bmkp-some (lambda (tag) (bmkp-string-match-p regexp (bmkp-tag-name tag)))
+ tags)))
+ (if (not (and tags (if notp (not anyp) anyp)))
+ (forward-line 1)
+ (bookmark-bmenu-mark 'NO-RE-SORT-P)
+ (setq count (1+ count)))))
+ (unless no-re-sort-p
+ ;; If some were unmarked before, and if sort order is `s >', then re-sort.
+ (when (and (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p))
+ (/= nb-marked (length bmkp-bmenu-marked-bookmarks)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk)))))
+ (when msg-p (if (= 1 count) (message "1 bookmark matched") (message "%d bookmarks matched" count)))))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-bookmarks-tagged-all "bookmark+")
+(defun bmkp-bmenu-mark-bookmarks-tagged-all (tags &optional nonep msg-p) ; `T m *' in bookmark list
+ "Mark all visible bookmarks that are tagged with *each* tag in TAGS.
+As a special case, if TAGS is empty, then mark the bookmarks that have
+any tags at all (i.e., at least one tag).
+
+With a prefix arg, mark all that are *not* tagged with *any* TAGS."
+ (interactive (list (bmkp-read-tags-completing) current-prefix-arg 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-bmenu-mark/unmark-bookmarks-tagged-all/none tags nonep nil nil msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-bookmarks-tagged-none "bookmark+")
+(defun bmkp-bmenu-mark-bookmarks-tagged-none (tags &optional allp msg-p) ; `T m ~ +' in bookmark list
+ "Mark all visible bookmarks that are not tagged with *any* tag in TAGS.
+As a special case, if TAGS is empty, then mark the bookmarks that have
+no tags at all.
+
+With a prefix arg, mark all that are tagged with *each* tag in TAGS."
+ (interactive (list (bmkp-read-tags-completing) current-prefix-arg 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-bmenu-mark/unmark-bookmarks-tagged-all/none tags (not allp) nil nil msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-bookmarks-tagged-some "bookmark+")
+(defun bmkp-bmenu-mark-bookmarks-tagged-some (tags &optional somenotp msg-p) ; `T m +' in bookmark list
+ "Mark all visible bookmarks that are tagged with *some* tag in TAGS.
+As a special case, if TAGS is empty, then mark the bookmarks that have
+any tags at all.
+
+With a prefix arg, mark all that are *not* tagged with *all* TAGS.
+
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+You can use completion to enter each tag."
+ (interactive (list (bmkp-read-tags-completing) current-prefix-arg 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-bmenu-mark/unmark-bookmarks-tagged-some/not-all tags somenotp nil nil msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-mark-bookmarks-tagged-not-all "bookmark+")
+(defun bmkp-bmenu-mark-bookmarks-tagged-not-all (tags &optional somep msg-p) ; `T m ~ *' in bmk list
+ "Mark all visible bookmarks that are *not* tagged with *all* TAGS.
+As a special case, if TAGS is empty, then mark the bookmarks that have
+no tags at all.
+
+With a prefix arg, mark all that are tagged with *some* tag in TAGS."
+ (interactive (list (bmkp-read-tags-completing) current-prefix-arg 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-bmenu-mark/unmark-bookmarks-tagged-some/not-all tags (not somep) nil nil msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-unmark-bookmarks-tagged-regexp "bookmark+")
+(defun bmkp-bmenu-unmark-bookmarks-tagged-regexp (regexp &optional notp no-re-sort-p msg-p)
+ ; `T u %' in bookmark list
+ "Unmark bookmarks any of whose tags match REGEXP.
+With a prefix arg, mark all that are tagged but have no matching tags.
+
+If any bookmark was marked before, and if the sort order is marked
+first or last (`s >'), then re-sort.
+
+Non-interactively:
+* Non-nil NOTP: see prefix arg, above.
+* Non-nil optional arg NO-RE-SORT-P inhibits re-sorting.
+* Non-nil optional arg MSG-P means display a status message."
+ (interactive (list (bmkp-read-regexp "Regexp: ") current-prefix-arg nil
+ (prefix-numeric-value current-prefix-arg)))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((count 0)
+ (nb-marked (length bmkp-bmenu-marked-bookmarks))
+ tags anyp)
+ (save-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (when msg-p (message "Updating bookmark-list display..."))
+ (while (not (eobp))
+ (setq tags (bmkp-get-tags (bookmark-bmenu-bookmark))
+ anyp (and tags (bmkp-some (lambda (tag) (bmkp-string-match-p regexp (bmkp-tag-name tag)))
+ tags)))
+ (if (not (and tags (if notp (not anyp) anyp)))
+ (forward-line 1)
+ (bookmark-bmenu-unmark nil 'NO-RE-SORT-P)
+ (setq count (1+ count)))))
+ (unless no-re-sort-p
+ ;; If some were marked before, and if sort order is `s >', then re-sort.
+ (when (and (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p))
+ (/= nb-marked (length bmkp-bmenu-marked-bookmarks)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk)))))
+ (when msg-p (if (= 1 count) (message "1 bookmark matched") (message "%d bookmarks matched" count)))))
+
+;;;###autoload (autoload 'bmkp-bmenu-unmark-bookmarks-tagged-all "bookmark+")
+(defun bmkp-bmenu-unmark-bookmarks-tagged-all (tags &optional nonep msg-p) ; `T u *' in bookmark list
+ "Unmark all visible bookmarks that are tagged with *each* tag in TAGS.
+As a special case, if TAGS is empty, then unmark the bookmarks that have
+any tags at all.
+
+With a prefix arg, unmark all that are *not* tagged with *any* TAGS."
+ (interactive (list (bmkp-read-tags-completing) current-prefix-arg 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-bmenu-mark/unmark-bookmarks-tagged-all/none tags nonep 'UNMARK nil msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-unmark-bookmarks-tagged-none "bookmark+")
+(defun bmkp-bmenu-unmark-bookmarks-tagged-none (tags &optional allp msg-p) ; `T u ~ +' in bookmark list
+ "Unmark all visible bookmarks that are *not* tagged with *any* TAGS.
+As a special case, if TAGS is empty, then unmark the bookmarks that have
+no tags at all.
+
+With a prefix arg, unmark all that are tagged with *each* tag in TAGS."
+ (interactive (list (bmkp-read-tags-completing) current-prefix-arg 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-bmenu-mark/unmark-bookmarks-tagged-all/none tags (not allp) 'UNMARK nil msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-unmark-bookmarks-tagged-some "bookmark+")
+(defun bmkp-bmenu-unmark-bookmarks-tagged-some (tags &optional somenotp msg-p) ; `T u +' in bmk list
+ "Unmark all visible bookmarks that are tagged with *some* tag in TAGS.
+As a special case, if TAGS is empty, then unmark the bookmarks that have
+any tags at all.
+
+With a prefix arg, unmark all that are *not* tagged with *all* TAGS."
+ (interactive (list (bmkp-read-tags-completing) current-prefix-arg 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-bmenu-mark/unmark-bookmarks-tagged-some/not-all tags somenotp 'UNMARK nil msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-unmark-bookmarks-tagged-not-all "bookmark+")
+(defun bmkp-bmenu-unmark-bookmarks-tagged-not-all (tags &optional somep msg-p) ; `T u ~ *' in bmk list
+ "Unmark all visible bookmarks that are *not* tagged with *all* TAGS.
+As a special case, if TAGS is empty, then unmark the bookmarks that have
+no tags at all.
+
+With a prefix arg, unmark all that are tagged with *some* TAGS."
+ (interactive (list (bmkp-read-tags-completing) current-prefix-arg 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-bmenu-mark/unmark-bookmarks-tagged-some/not-all tags (not somep) 'UNMARK nil msg-p))
+
+(defun bmkp-bmenu-mark/unmark-bookmarks-tagged-all/none (tags &optional nonep unmarkp no-re-sort-p msg-p)
+ "Mark or unmark visible bookmarks tagged with all or none of TAGS.
+TAGS is a list of strings, the tag names.
+Non-nil NONEP means mark/unmark bookmarks that have none of the TAGS.
+Non-nil UNMARKP means unmark; nil means mark.
+Non-nil NO-RE-SORT-P inhibits re-sorting.
+Non-nil MSG-P means display a status message.
+
+As a special case, if TAGS is empty, then mark or unmark the bookmarks
+that have any tags at all, or if NONEP is non-nil then mark or unmark
+those that have no tags at all.
+
+If any bookmark was (un)marked before but is not afterward, and if the
+sort order is marked first or last (`s >'), then re-sort."
+ (with-current-buffer bmkp-bmenu-buffer
+ (let ((count 0)
+ (nb-marked (length bmkp-bmenu-marked-bookmarks))
+ bmktags presentp)
+ (save-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (when msg-p (message "Updating bookmark-list display..."))
+ (while (not (eobp))
+ (setq bmktags (bmkp-get-tags (bookmark-bmenu-bookmark)))
+ (if (not (if (null tags)
+ (if nonep (not bmktags) bmktags)
+ (and bmktags (catch 'bmkp-b-mu-b-t-an
+ (dolist (tag tags)
+ (setq presentp (assoc-default tag bmktags nil t))
+ (unless (if nonep (not presentp) presentp)
+ (throw 'bmkp-b-mu-b-t-an nil)))
+ t))))
+ (forward-line 1)
+ (if unmarkp (bookmark-bmenu-unmark nil 'NO-RE-SORT-P) (bookmark-bmenu-mark 'NO-RE-SORT-P))
+ (setq count (1+ count)))))
+ (unless no-re-sort-p
+ ;; If some were (un)marked before but not afterward, and if sort order is `s >', then re-sort.
+ (when (and (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p))
+ (/= nb-marked (length bmkp-bmenu-marked-bookmarks)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk)))))
+ (when msg-p
+ (if (= 1 count) (message "1 bookmark matched") (message "%d bookmarks matched" count))))))
+
+(defun bmkp-bmenu-mark/unmark-bookmarks-tagged-some/not-all (tags &optional notallp unmarkp
+ no-re-sort-p msg-p)
+ "Mark or unmark visible bookmarks tagged with any or not all of TAGS.
+TAGS is a list of strings, the tag names.
+Non-nil NOTALLP means mark/unmark bookmarks that do not have all TAGS.
+Non-nil UNMARKP means unmark; nil means mark.
+Non-nil NO-RE-SORT-P inhibits re-sorting.
+Non-nil MSG-P means display a status message.
+
+As a special case, if TAGS is empty, then mark or unmark the bookmarks
+that have any tags at all, or if NOTALLP is non-nil then mark or
+unmark those that have no tags at all.
+
+If any bookmark was (un)marked before but is not afterward, and if the
+sort order is marked first or last (`s >'), then re-sort."
+ (with-current-buffer bmkp-bmenu-buffer
+ (let ((count 0)
+ (nb-marked (length bmkp-bmenu-marked-bookmarks))
+ bmktags presentp)
+ (save-excursion
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (when msg-p (message "Updating bookmark-list display..."))
+ (while (not (eobp))
+ (setq bmktags (bmkp-get-tags (bookmark-bmenu-bookmark)))
+ (if (not (if (null tags)
+ (if notallp (not bmktags) bmktags)
+ (and bmktags (catch 'bmkp-b-mu-b-t-sna
+ (dolist (tag tags)
+ (setq presentp (assoc-default tag bmktags nil t))
+ (when (if notallp (not presentp) presentp)
+ (throw 'bmkp-b-mu-b-t-sna t)))
+ nil))))
+ (forward-line 1)
+ (if unmarkp (bookmark-bmenu-unmark nil 'NO-RE-SORT-P) (bookmark-bmenu-mark 'NO-RE-SORT-P))
+ (setq count (1+ count)))))
+ (unless no-re-sort-p
+ ;; If some were (un)marked before but not afterward, and if sort order is `s >', then re-sort.
+ (when (and (equal bmkp-sort-comparer '((bmkp-marked-cp) bmkp-alpha-p))
+ (/= nb-marked (length bmkp-bmenu-marked-bookmarks)))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk (bmkp-bmenu-goto-bookmark-named curr-bmk)))))
+ (when msg-p
+ (if (= 1 count) (message "1 bookmark matched") (message "%d bookmarks matched" count))))))
+
+;;;###autoload (autoload 'bmkp-bmenu-copy-tags "bookmark+")
+(defun bmkp-bmenu-copy-tags (&optional msg-p) ; `T c', `T M-w', `mouse-3' menu in bookmark list.
+ "Copy tags from this bookmark, so you can paste them to another bookmark.
+NOTE: It is by design that you can *remove all* tags from a bookmark
+by copying an empty set of tags and then pasting to that bookmark
+using replacement. So be careful pasting with replacement. If you
+want to be sure that you do not replace tags with an empty list of
+tags, you can check the value of variable `bmkp-copied-tags' before
+pasting."
+ (interactive (list 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (bmkp-copy-tags (bookmark-bmenu-bookmark) msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-paste-add-tags "bookmark+")
+(defun bmkp-bmenu-paste-add-tags (&optional msg-p) ; `T p', `T C-y', `mouse-3' menu in bookmark list.
+ "Add tags to this bookmark that were copied from another bookmark."
+ (interactive (list 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (bmkp-paste-add-tags (bookmark-bmenu-bookmark) nil msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-paste-replace-tags "bookmark+")
+(defun bmkp-bmenu-paste-replace-tags (&optional msg-p) ; `T q', `mouse-3' menu.
+ "Replace tags for this bookmark with those copied from another bookmark.
+NOTE: It is by design that you can *remove all* tags from a bookmark
+by copying an empty set of tags and then pasting to that bookmark
+using this command. So be careful using it. If you want to be sure
+that you do not replace tags with an empty list of tags, you can check
+the value of variable `bmkp-copied-tags' before pasting."
+ (interactive (list 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (bmkp-paste-replace-tags (bookmark-bmenu-bookmark) nil msg-p))
+
+;;;###autoload (autoload 'bmkp-bmenu-paste-add-tags-to-marked "bookmark+")
+(defun bmkp-bmenu-paste-add-tags-to-marked (&optional allp include-omitted-p msg-p)
+ ; Bound to `T > p', `T > C-y' in bookmark list
+ "Add tags that were copied from another bookmark to the marked bookmarks.
+If no bookmark is marked, act on the bookmark of the current line.
+
+With a non-negative prefix arg, act on all bookmarks.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included.
+
+Non-interactively, non-nil MSG-P means display messages."
+ (interactive (list (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))
+ 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((marked (bmkp-bmenu-marked-or-this-or-all allp include-omitted-p))
+ (bmk (bookmark-bmenu-bookmark)))
+ (unless marked (error "No marked bookmarks"))
+ (when msg-p (message "Adding tags..."))
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bmk marked) (bmkp-paste-add-tags bmk 'NO-UPDATE-P)))
+ (bmkp-tags-list) ; Update the tags cache now, after iterate.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh-menu-list bmk (not msg-p)) ; Refresh after iterate.
+ (when msg-p (message "Tags added: %S" bmkp-copied-tags))))
+
+;;;###autoload (autoload 'bmkp-bmenu-paste-replace-tags-for-marked "bookmark+")
+(defun bmkp-bmenu-paste-replace-tags-for-marked (&optional allp include-omitted-p msg-p) ; `T > q'
+ "Replace tags for the marked bookmarks with tags copied previously.
+NOTE: It is by design that you can *remove all* tags from a bookmark
+by copying an empty set of tags and then pasting to that bookmark
+using this command. So be careful using it. If you want to be sure
+that you do not replace tags with an empty list of tags, you can check
+the value of variable `bmkp-copied-tags' before pasting.
+
+If no bookmark is marked, act on the bookmark of the current line.
+
+With a non-negative prefix arg, act on all bookmarks.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included.
+
+Non-interactively, non-nil MSG-P means display messages."
+ (interactive (list (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))
+ 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((marked (bmkp-bmenu-marked-or-this-or-all allp include-omitted-p))
+ (bmk (bookmark-bmenu-bookmark)))
+ (unless marked (error "No marked bookmarks"))
+ (when msg-p (message "Replacing tags..."))
+ (let ((bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
+ bookmark-save-flag))) ; Save at most once, after `dolist'.
+ (dolist (bmk marked) (bmkp-paste-replace-tags bmk 'NO-UPDATE-P)))
+ (bmkp-tags-list) ; Update the tags cache now, after iterate.
+ (bmkp-maybe-save-bookmarks) ; Increments `bookmark-alist-modification-count'.
+ (bmkp-refresh-menu-list bmk (not msg-p)) ; Refresh after iterate.
+ (when msg-p (message "Replacement tags: %S" bmkp-copied-tags))))
+
+
+;;(@* "General Menu-List (`-*bmenu-*') Commands and Functions")
+;; *** General Menu-List (`-*bmenu-*') Commands and Functions ***
+
+;;;###autoload (autoload 'bmkp-bmenu-create/edit-annotations-for-marked "bookmark+")
+(defun bmkp-bmenu-edit-annotations-for-marked (&optional allp include-omitted-p) ; `a >' in bookmark list
+ "Edit the annotations of the marked bookmarks, in separate buffers.
+Create an annotation for any marked bookmark that has none.
+When you finish editing, use `\\[bmkp-edit-annotations-send]'.
+The current bookmark list is then updated to reflect your edits.
+
+If no bookmark is marked, edit the annotation of the bookmark of the
+current line.
+
+With a non-negative prefix arg, edit annotations for all bookmarks.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included."
+ (interactive (list (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (setq bmkp-last-bmenu-bookmark (bookmark-bmenu-bookmark))
+ ;; No marked bookmarks. Mark this bookmark, so that `C-c C-c' in edit buffer will find it.
+ (unless bmkp-bmenu-marked-bookmarks (bookmark-bmenu-mark))
+ ;; FIXME - Should we re-sort, if it was not annotated and now is, or vice versa, and if `s a'?
+ ;; We do that for adding/removing tags - see `bmkp-bmenu-add-tags' and `bmkp-bmenu-remove-tags'.
+ ;; If we do it, then do it also for `bookmark-bmenu-edit-annotation' (which is just vanilla, so far).
+ (let ((bmks (bmkp-bmenu-marked-or-this-or-all allp include-omitted-p)))
+ (unless bmks (error "No marked bookmarks"))
+ (dolist (bmk (bmkp-sort-omit bmks)) (bookmark-edit-annotation bmk))))
+
+;;;###autoload (autoload 'bmkp-bmenu-show-or-edit-annotation "bookmark+")
+(defun bmkp-bmenu-show-or-edit-annotation (editp msg-p) ; Not bound anymore.
+ "Show annotation for current bookmark in another window. `C-u': Edit.
+With no prefix arg, show the annotation. With a prefix arg, edit it."
+ (interactive "P\np")
+ (if editp (bookmark-bmenu-edit-annotation) (bookmark-bmenu-show-annotation msg-p)))
+
+;;;###autoload (autoload 'bmkp-bmenu-jump-to-marked "bookmark+")
+(defun bmkp-bmenu-jump-to-marked ()
+ "Jump to each bookmark marked `>', in another window.
+Unlike `bookmark-bmenu-select', this command:
+* does not bury buffer `*Bookmark List*' or replace it in its window
+* does not unmark the marked bookmarks
+* does not include the current bookmark - only the marked are accessed"
+ (interactive)
+ (dolist (bmk bmkp-bmenu-marked-bookmarks)
+ (bookmark-jump-other-window bmk)))
+
+;;;###autoload (autoload 'bmkp-bmenu-w32-open "bookmark+")
+(defun bmkp-bmenu-w32-open () ; Bound to `M-RET' in bookmark list.
+ "Use `w32-browser' to open this bookmark."
+ (interactive) (let ((bmkp-use-w32-browser-p t)) (bookmark-bmenu-this-window)))
+
+;; $$$$$$ FIXME?: If `Open' action opens a window-manager window, it might be behind all Emacs frames.
+;;;###autoload (autoload 'bmkp-bmenu-w32-open-with-mouse "bookmark+")
+(defun bmkp-bmenu-w32-open-with-mouse (event) ; Bound to `M-mouse-2' in bookmark list.
+ "Use `w32-browser' to open the bookmark clicked."
+ (interactive "e")
+ (let ((bmkp-use-w32-browser-p t)
+ (bmk (with-current-buffer (window-buffer (posn-window (event-end event)))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (save-excursion (goto-char (posn-point (event-end event)))
+ (bookmark-bmenu-bookmark)))))
+ (unless bmk (error "No bookmark here"))
+ (bookmark-handle-bookmark bmk)
+ ;; Probably do not want this. Users can use `jump-fn' tag if need be.
+ ;; (let ((orig-buff (current-buffer))) ; Used by `crosshairs-highlight'.
+ ;; (run-hooks 'bookmark-after-jump-hook))
+ (let ((jump-fn (bmkp-get-tag-value bmk "bmkp-jump")))
+ (when jump-fn (funcall jump-fn)))
+ (when bookmark-automatically-show-annotations (bookmark-show-annotation bmk))))
+
+;;;###autoload (autoload 'bmkp-bmenu-w32-jump-to-marked "bookmark+")
+(defun bmkp-bmenu-w32-jump-to-marked () ; Bound to `M-o' in bookmark-list.
+ "Use `w32-browser' to open this bookmark and all marked bookmarks."
+ (interactive) (let ((bmkp-use-w32-browser-p t)) (bmkp-bmenu-jump-to-marked)))
+
+;;;###autoload (autoload 'bmkp-bmenu-mode-status-help "bookmark+")
+(defun bmkp-bmenu-mode-status-help () ; Bound to `C-h m' and `?' in bookmark list
+ "`describe-mode' + current status of `*Bookmark List*' + face legend."
+ (interactive)
+ (unless (string= (buffer-name) "*Help*") (bmkp-bmenu-barf-if-not-in-menu-list))
+ (with-current-buffer (get-buffer-create "*Help*")
+ (bmkp-with-help-window "*Help*"
+ (let ((buffer-read-only nil)
+ top)
+ (erase-buffer)
+ (save-excursion
+ (let ((standard-output (current-buffer)))
+ (if (> emacs-major-version 21)
+ (describe-function-1 'bookmark-bmenu-mode)
+ (describe-function-1 'bookmark-bmenu-mode nil t)))
+ (help-setup-xref (list #'bmkp-bmenu-mode-status-help) (interactive-p))
+ (goto-char (point-min))
+ (search-forward ; This depends on the text written by `bookmark-bmenu-mode'.
+ "More bookmarking help below." nil t)
+ (delete-region (point-min) (point)) ; Get rid of intro from `describe-function'.
+ (insert "*************************** Bookmark List ***************************\n\n")
+ (insert "Major mode for editing a list of bookmarks.\n")
+ (insert "Each line in `*Bookmark List*' represents an Emacs bookmark.\n")
+ (setq top (copy-marker (point)))
+ ;; Add buttons to access help and Customize.
+ ;; Not for Emacs 21.3 - its `help-insert-xref-button' signature is different.
+ (when (and (> emacs-major-version 21) ; In `help-mode.el'.
+ (condition-case nil (require 'help-mode nil t) (error nil))
+ (fboundp 'help-insert-xref-button))
+ (goto-char (point-min))
+ (help-insert-xref-button "[Doc in Commentary]" 'bmkp-commentary-button)
+ (insert " ")
+ (help-insert-xref-button "[Doc on the Web]" 'bmkp-help-button)
+ (insert " ")
+ (help-insert-xref-button "[Customize]" 'bmkp-customize-button)
+ (insert "\n\n")
+ (goto-char (point-max))
+ (insert (substitute-command-keys
+ "\nSend a Bookmark+ bug report: `\\[bmkp-send-bug-report]'.\n\n"))
+ (help-insert-xref-button "[Doc in Commentary]" 'bmkp-commentary-button)
+ (insert " ")
+ (help-insert-xref-button "[Doc on the Web]" 'bmkp-help-button)
+ (insert " ")
+ (help-insert-xref-button "[Customize]" 'bmkp-customize-button)
+ (insert "\n\n")
+ (goto-char (point-min))
+ (forward-line 2))
+ (goto-char top)
+ (insert (format
+ "\n\nCurrent Status\n--------------\n
+Bookmark file:\t%s\nSorted:\t\t\t%s\nFiltering:\t\t%s\nMarked:\t\t\t%d\nOmitted:\t\t%d\n\
+Autosave bookmarks:\t%s\nAutosave list display:\t%s\n\n\n"
+ bmkp-current-bookmark-file
+ (if (not bmkp-sort-comparer)
+ "no"
+ (format "%s%s" (or (bmkp-current-sort-order) "")
+ ;; Code essentially the same as found in `bmkp-msg-about-sort-order'.
+ (if (not (and (consp bmkp-sort-comparer) ; Ordinary single predicate
+ (consp (car bmkp-sort-comparer))))
+ (if bmkp-reverse-sort-p "; reversed" "")
+ (if (not (cadr (car bmkp-sort-comparer)))
+ ;; Single PRED.
+ (if (or (and bmkp-reverse-sort-p (not bmkp-reverse-multi-sort-p))
+ (and bmkp-reverse-multi-sort-p (not bmkp-reverse-sort-p)))
+ "; reversed"
+ "")
+ ;; In case we want to distinguish:
+ ;; (if (and bmkp-reverse-sort-p
+ ;; (not bmkp-reverse-multi-sort-p))
+ ;; "; reversed"
+ ;; (if (and bmkp-reverse-multi-sort-p
+ ;; (not bmkp-reverse-sort-p))
+ ;; "; reversed +"
+ ;; ""))
+
+ ;; At least two PREDs.
+ (cond ((and bmkp-reverse-sort-p (not bmkp-reverse-multi-sort-p))
+ "; reversed")
+ ((and bmkp-reverse-multi-sort-p (not bmkp-reverse-sort-p))
+ "; each predicate group reversed")
+ ((and bmkp-reverse-multi-sort-p bmkp-reverse-sort-p)
+ "; order of predicate groups reversed")
+ (t ""))))))
+ (or (and bmkp-bmenu-filter-function (downcase bmkp-bmenu-title)) "none")
+ (length bmkp-bmenu-marked-bookmarks)
+ (length bmkp-bmenu-omitted-bookmarks)
+ (if bookmark-save-flag "yes" "no")
+ (if bmkp-bmenu-state-file "yes" "no")))
+
+ ;; Add markings legend.
+ (let ((mm " >")
+ (DD " D")
+ (tt " t")
+ (aa " a")
+ (XX " X")
+ (mod " *"))
+ (put-text-property 2 3 'face 'bmkp->-mark mm)
+ (put-text-property 2 3 'face 'bmkp-D-mark DD)
+ (put-text-property 2 3 'face 'bmkp-t-mark tt)
+ (put-text-property 2 3 'face 'bmkp-a-mark aa)
+ (put-text-property 2 3 'face 'bmkp-X-mark XX)
+ (put-text-property 2 3 'face 'bmkp-*-mark mod)
+ (insert "Legend for Markings\n-------------------\n\n")
+ (insert (concat mm " marked\n"))
+ (insert (concat DD " flagged for deletion (`x' to delete all such)\n"))
+ (insert (concat tt " tagged (`C-h C-RET' to see)\n"))
+ (insert (concat aa " annotated (`C-h C-RET' to see)\n"))
+ (insert (concat mod " modified (not saved)\n"))
+ (insert (concat XX " temporary (will not be saved)\n"))
+ (insert "\n\n"))
+
+ ;; Add face legend.
+ (let ((gnus "Gnus\n")
+ (no-jump "Bookmarks you cannot jump to from `*Bookmark List*'\n")
+ (info "Info node\n")
+ (man "Man page\n")
+ (url "URL\n")
+ (local-no-region "Local file with no region\n")
+ (local-w-region "Local file with a region\n")
+ (no-file "No such local file\n")
+ (buffer "Buffer\n")
+ (no-buf "No such buffer now\n")
+ (bad "Possibly invalid bookmark\n")
+ (remote "Remote file/directory or Dired buffer (could have wildcards)\n")
+ (sudo "Remote accessed by `su' or `sudo'\n")
+ (local-dir "Local directory or Dired buffer (could have wildcards)\n")
+ (file-handler "Bookmark with entry `file-handler'\n")
+ (bookmark-list "*Bookmark List*\n")
+ (bookmark-file "Bookmark file\n")
+ (snippet "Snippet\n")
+ (desktop "Desktop\n")
+ (sequence "Sequence\n")
+ (variable-list "Variable list\n")
+ (function "Function\n"))
+ (put-text-property 0 (1- (length gnus)) 'face 'bmkp-gnus gnus)
+ (put-text-property 0 (1- (length info)) 'face 'bmkp-info info)
+ (put-text-property 0 (1- (length man)) 'face 'bmkp-man man)
+ (put-text-property 0 (1- (length url)) 'face 'bmkp-url url)
+ (put-text-property 0 (1- (length local-no-region))
+ 'face 'bmkp-local-file-without-region local-no-region)
+ (put-text-property 0 (1- (length local-w-region))
+ 'face 'bmkp-local-file-with-region local-w-region)
+ (put-text-property 0 (1- (length no-file)) 'face 'bmkp-no-local no-file)
+ (put-text-property 0 (1- (length buffer)) 'face 'bmkp-buffer buffer)
+ (put-text-property 0 (1- (length no-buf)) 'face 'bmkp-non-file no-buf)
+ (put-text-property 0 (1- (length remote)) 'face 'bmkp-remote-file remote)
+ (put-text-property 0 (1- (length sudo)) 'face 'bmkp-su-or-sudo sudo)
+ (put-text-property 0 (1- (length local-dir))
+ 'face 'bmkp-local-directory local-dir)
+ (put-text-property 0 (1- (length file-handler)) 'face 'bmkp-file-handler file-handler)
+ (put-text-property 0 (1- (length bookmark-list))
+ 'face 'bmkp-bookmark-list bookmark-list)
+ (put-text-property 0 (1- (length bookmark-file))
+ 'face 'bmkp-bookmark-file bookmark-file)
+ (put-text-property 0 (1- (length snippet)) 'face 'bmkp-snippet snippet)
+ (put-text-property 0 (1- (length desktop)) 'face 'bmkp-desktop desktop)
+ (put-text-property 0 (1- (length sequence)) 'face 'bmkp-sequence sequence)
+ (put-text-property 0 (1- (length variable-list)) 'face 'bmkp-variable-list variable-list)
+ (put-text-property 0 (1- (length function)) 'face 'bmkp-function function)
+ (put-text-property 0 (1- (length no-jump)) 'face 'bmkp-no-jump no-jump)
+ (put-text-property 0 (1- (length bad)) 'face 'bmkp-bad-bookmark bad)
+ (insert "Legend for Bookmark Types\n-------------------------\n\n")
+ (when (and (fboundp 'display-images-p) (display-images-p)
+ bmkp-bmenu-image-bookmark-icon-file
+ (file-readable-p bmkp-bmenu-image-bookmark-icon-file))
+ (let ((image (create-image bmkp-bmenu-image-bookmark-icon-file nil nil :ascent 95)))
+ (when image (insert " ") (insert-image image) (insert " Image file\n"))))
+ (insert " " gnus) (insert " " info) (insert " " man) (insert " " url)
+ (insert " " local-no-region) (insert " " local-w-region) (insert " " no-file)
+ (insert " " buffer) (insert " " no-buf) (insert " " remote) (insert " " sudo)
+ (insert " " local-dir) (insert " " file-handler) (insert " " bookmark-list)
+ (insert " " bookmark-file) (insert " " snippet) (insert " " desktop)
+ (insert " " sequence) (insert " " variable-list) (insert " " function)
+ (insert " " no-jump) (insert " " bad)
+ (insert "\n\nKeys without prefix `C-x' are available only here (`*Bookmark List*').\n")
+ (insert "Keys with prefix `C-x' are available everywhere.\n\n")
+ (insert "Remember that you can see all bindings for a prefix key by hitting it,\n")
+ (insert "then `C-h'. E.g., `s C-h' to see keys with prefix `s' (sorting).")))))))
+
+(when (and (> emacs-major-version 21)
+ (condition-case nil (require 'help-mode nil t) (error nil))
+ (get 'help-xref 'button-category-symbol)) ; In `button.el'
+ (define-button-type 'bmkp-help-button
+ :supertype 'help-xref
+ 'help-function #'(lambda () (browse-url "https://www.emacswiki.org/emacs/BookmarkPlus"))
+ 'help-echo
+ (purecopy "mouse-2, RET: Bookmark+ documentation on the Emacs Wiki (requires Internet access)"))
+ (define-button-type 'bmkp-commentary-button
+ :supertype 'help-xref
+ 'help-function #'(lambda ()
+ (message "Getting Bookmark+ doc from file commentary...")
+ (finder-commentary "bookmark+-doc")
+ (when (condition-case nil (require 'linkd nil t) (error nil)) (linkd-mode 1))
+ (when (condition-case nil (require 'fit-frame nil t) (error nil))
+ (fit-frame)))
+ 'help-echo (purecopy "mouse-2, RET: Bookmark+ documentation (no Internet needed)"))
+ (define-button-type 'bmkp-customize-button
+ :supertype 'help-xref
+ 'help-function #'(lambda () (customize-group-other-window 'bookmark-plus))
+ 'help-echo (purecopy "mouse-2, RET: Customize/Browse Bookmark+ Options & Faces")))
+
+;;;###autoload (autoload 'bmkp-bmenu-define-jump-marked-command "bookmark+")
+(defun bmkp-bmenu-define-jump-marked-command () ; Bound to `C-c C-j' in bookmark list
+ "Define a command to jump to a bookmark that is one of those now marked.
+The bookmarks marked now will be those that are completion candidates
+for the command (but omitted bookmarks are excluded).
+Save the command definition in `bmkp-bmenu-commands-file'."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let* ((cands (mapcar #'list
+ (bmkp-maybe-unpropertize-bookmark-names
+ (bmkp-remove-if #'(lambda (bmk)
+ (bmkp-bookmark-name-member bmk bmkp-bmenu-omitted-bookmarks))
+ bmkp-bmenu-marked-bookmarks))))
+ (fn (intern (read-string "Define command to jump to a bookmark now marked: " nil
+ bmkp-bmenu-define-command-history)))
+ (def `(defun ,fn (bookmark-name &optional flip-use-region-p)
+ (interactive (list (bmkp-read-bookmark-for-type nil ',cands t) current-prefix-arg))
+ (bmkp-jump-1 bookmark-name 'bmkp-select-buffer-other-window flip-use-region-p))))
+ (eval def)
+ (with-current-buffer (find-file-noselect bmkp-bmenu-commands-file)
+ (goto-char (point-max))
+ (let ((print-length nil)
+ (print-level nil)
+ (print-circle bmkp-propertize-bookmark-names-flag)
+ (print-gensym bmkp-propertize-bookmark-names-flag)
+ (version-control (case bookmark-version-control
+ ((nil) nil)
+ (never 'never)
+ (nospecial version-control)
+ (t t)))
+ (require-final-newline t)
+ (errorp nil))
+ (pp def (current-buffer))
+ (insert "\n")
+ (condition-case nil
+ (write-file bmkp-bmenu-commands-file)
+ (file-error (setq errorp t) (error "CANNOT WRITE FILE `%s'" bmkp-bmenu-commands-file)))
+ (kill-buffer (current-buffer))
+ (unless errorp (message "Command `%s' defined and saved in file `%s'"
+ fn bmkp-bmenu-commands-file))))))
+
+;;;###autoload (autoload 'bmkp-bmenu-define-command "bookmark+")
+(defun bmkp-bmenu-define-command () ; Bound to `C-c C-c' in bookmark list
+ "Define a command to use the current sort order, filter, and omit list.
+Prompt for the command name. Save the command definition in
+`bmkp-bmenu-commands-file'.
+
+The current sort order, filter function, omit list, and title for
+buffer `*Bookmark List*' are encapsulated as part of the command.
+Use the command at any time to restore them."
+ (interactive)
+ (let* ((fn (intern (read-string "Define sort+filter command: " nil
+ bmkp-bmenu-define-command-history)))
+ (_IGNORE (when (fboundp fn)
+ (if (y-or-n-p (format "`%s' already defined. Redfine? " fn))
+ (fmakunbound fn)
+ (error "OK, canceled"))))
+ (def `(defun ,fn ()
+ (interactive)
+ (setq
+ bmkp-sort-comparer ',bmkp-sort-comparer
+ bmkp-reverse-sort-p ',bmkp-reverse-sort-p
+ bmkp-reverse-multi-sort-p ',bmkp-reverse-multi-sort-p
+ bmkp-bmenu-filter-function ',bmkp-bmenu-filter-function
+ bmkp-bmenu-filter-pattern ',bmkp-bmenu-filter-pattern
+ ;; Use `copy-sequence' here, because some code modifies the list structure.
+ bmkp-bmenu-omitted-bookmarks (copy-sequence
+ ',(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-omitted-bookmarks))
+ bmkp-bmenu-title ',bmkp-bmenu-title
+ bookmark-bmenu-toggle-filenames ',bookmark-bmenu-toggle-filenames)
+ (bmkp-bmenu-refresh-menu-list)
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order
+ (car (rassoc bmkp-sort-comparer bmkp-sort-orders-alist)))))))
+ (eval def)
+ (with-current-buffer (find-file-noselect bmkp-bmenu-commands-file)
+ (goto-char (point-min)) ; Delete any preexisting defs of the same command.
+ (let (sexp)
+ (condition-case nil
+ (while (setq sexp (read (current-buffer)))
+ (when (and (consp sexp) (eq 'defun (car sexp))
+ (eq fn (cadr sexp)))
+ (delete-region (point) (save-excursion (backward-sexp) (point)))))
+ (error nil)))
+ (goto-char (point-max))
+ (let ((print-length nil)
+ (print-level nil)
+ (print-circle bmkp-propertize-bookmark-names-flag)
+ (print-gensym bmkp-propertize-bookmark-names-flag)
+ (version-control (case bookmark-version-control
+ ((nil) nil)
+ (never 'never)
+ (nospecial version-control)
+ (t t)))
+ (require-final-newline t)
+ (errorp nil))
+ (pp def (current-buffer))
+ (insert "\n")
+ (condition-case nil
+ (write-file bmkp-bmenu-commands-file)
+ (file-error (setq errorp t) (error "CANNOT WRITE FILE `%s'" bmkp-bmenu-commands-file)))
+ (kill-buffer (current-buffer))
+ (unless errorp (message "Command `%s' defined and saved in file `%s'"
+ fn bmkp-bmenu-commands-file))))))
+
+;;;###autoload (autoload 'bmkp-bmenu-define-full-snapshot-command "bookmark+")
+(defun bmkp-bmenu-define-full-snapshot-command () ; Bound to `C-c C-S-c' (aka `C-c C-C') in bookmark list
+ "Define a command to restore the current bookmark-list state.
+Prompt for the command name. Save the command definition in
+`bmkp-bmenu-commands-file'.
+
+Be aware that the command definition can be quite large, since it
+copies the current bookmark list and accessory lists (hidden
+bookmarks, marked bookmarks, etc.). For a lighter weight command, use
+`bmkp-bmenu-define-full-snapshot-command' instead. That records only
+the omit list and the sort & filter information."
+ (interactive)
+ (let* ((fn (intern (read-string "Define restore-snapshot command: " nil
+ bmkp-bmenu-define-command-history)))
+ (_IGNORE (when (fboundp fn)
+ (if (y-or-n-p (format "`%s' already defined. Redfine? " fn))
+ (fmakunbound fn)
+ (error "OK, canceled"))))
+ (def `(defun ,fn ()
+ (interactive)
+ ;; Use `copy-sequence' here, to avoid circular references when
+ ;; `bmkp-propertize-bookmark-names-flag' is nil, and for other
+ ;; strings and lists (such as `bmkp-bmenu-marked-bookmarks'),
+ ;; because some code modifies them.
+ ;;
+ (setq
+ bmkp-sort-comparer ',bmkp-sort-comparer
+ bmkp-reverse-sort-p ',bmkp-reverse-sort-p
+ bmkp-reverse-multi-sort-p ',bmkp-reverse-multi-sort-p
+ bmkp-latest-bookmark-alist (copy-sequence
+ ',(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-latest-bookmark-alist))
+ bmkp-bmenu-omitted-bookmarks (copy-sequence
+ ',(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-omitted-bookmarks 'COPY))
+ bmkp-bmenu-marked-bookmarks (copy-sequence
+ ',(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-marked-bookmarks 'COPY))
+ bmkp-bmenu-filter-function ',bmkp-bmenu-filter-function
+ bmkp-bmenu-filter-pattern ',bmkp-bmenu-filter-pattern
+ bmkp-bmenu-title ',bmkp-bmenu-title
+ bmkp-last-bmenu-bookmark ',(and (get-buffer bmkp-bmenu-buffer)
+ (with-current-buffer
+ (get-buffer bmkp-bmenu-buffer)
+ (bmkp-maybe-unpropertize-string
+ (bookmark-bmenu-bookmark) 'COPY)))
+ bmkp-last-specific-buffer ',(copy-sequence bmkp-last-specific-buffer)
+ bmkp-last-specific-file ',(copy-sequence bmkp-last-specific-file)
+ bookmark-bmenu-toggle-filenames ',bookmark-bmenu-toggle-filenames
+ bmkp-bmenu-before-hide-marked-alist (copy-sequence
+ ',(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-before-hide-marked-alist 'COPY))
+ bmkp-bmenu-before-hide-unmarked-alist (copy-sequence
+ ',(bmkp-maybe-unpropertize-bookmark-names
+ bmkp-bmenu-before-hide-unmarked-alist 'COPY))
+ bmkp-last-bookmark-file ',(copy-sequence
+ (convert-standard-filename
+ (expand-file-name bmkp-last-bookmark-file)))
+ bmkp-current-bookmark-file ',(copy-sequence
+ (convert-standard-filename
+ (expand-file-name
+ bmkp-current-bookmark-file))))
+ ;; $$$$$$ (let ((bookmark-alist (bmkp-refresh-latest-bookmark-list))) ; Sets *-latest-* also.
+ (let ((bookmark-alist (or bmkp-latest-bookmark-alist
+ (bmkp-refresh-latest-bookmark-list)))) ; Sets *-latest-* also.
+ (bmkp-bmenu-list-1 'filteredp nil (interactive-p)))
+ (when bmkp-last-bmenu-bookmark
+ (with-current-buffer (get-buffer bmkp-bmenu-buffer)
+ (bmkp-bmenu-goto-bookmark-named bmkp-last-bmenu-bookmark)))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (car (rassoc bmkp-sort-comparer bmkp-sort-orders-alist)))))))
+ (eval def)
+ (with-current-buffer (find-file-noselect bmkp-bmenu-commands-file)
+ (goto-char (point-min)) ; Delete any preexisting defs of the same command.
+ (let (sexp)
+ (condition-case nil
+ (while (setq sexp (read (current-buffer)))
+ (when (and (consp sexp) (eq 'defun (car sexp))
+ (eq fn (cadr sexp)))
+ (delete-region (point) (save-excursion (backward-sexp) (point)))))
+ (error nil)))
+ (goto-char (point-max))
+ (let ((print-length nil)
+ (print-level nil)
+ (print-circle bmkp-propertize-bookmark-names-flag)
+ (print-gensym bmkp-propertize-bookmark-names-flag)
+ (version-control (case bookmark-version-control
+ ((nil) nil)
+ (never 'never)
+ (nospecial version-control)
+ (t t)))
+ (require-final-newline t)
+ (errorp nil))
+ (pp def (current-buffer))
+ (insert "\n")
+ (condition-case nil
+ (write-file bmkp-bmenu-commands-file)
+ (file-error (setq errorp t) (error "CANNOT WRITE FILE `%s'" bmkp-bmenu-commands-file)))
+ (kill-buffer (current-buffer))
+ (unless errorp (message "Command `%s' defined and saved in file `%s'"
+ fn bmkp-bmenu-commands-file))))))
+
+;; We use this because Emacs 20 has no `print-circle' or `print-gensym'. and otherwise
+;; property `bmkp-full-record' would make the state file unreadable.
+;;
+(defun bmkp-maybe-unpropertize-bookmark-names (list &optional copy)
+ "Strip properties from the bookmark names in a copy of LIST.
+LIST is a bookmark alist or a list of bookmark names (strings).
+Return the updated copy.
+
+Note, however, that this is a shallow copy, so the names are also
+stripped within any alist elements of the original LIST.
+
+Non-nil optional arg COPY means copy also each element of LIST. Use
+this if, for example, you have bookmark lists that share bookmarks and
+you want to treat the shared bookmarks separately.
+
+Always strip property `face' and internal Icicles properties. Remove
+other text properties only if using Emacs 20 or if option
+`bmkp-propertize-bookmark-names-flag' is non-nil."
+ (let ((new-list (copy-sequence list))
+ (rem-all-p (or (not bmkp-propertize-bookmark-names-flag)
+ (< emacs-major-version 21)))) ; Cannot just use (not (boundp 'print-circle)).
+ (dolist (bmk new-list)
+ (when (and (consp bmk) (stringp (car bmk))) (setq bmk (car bmk)))
+ (when (stringp bmk)
+ (let ((len (length bmk)))
+ (if rem-all-p
+ (set-text-properties 0 len nil bmk)
+ (remove-text-properties ; Remove property `face' and any Icicles internal properties.
+ 0 len '(face nil
+ display nil
+ help-echo nil
+ rear-nonsticky nil
+ icicle-fancy-candidates nil
+ icicle-mode-line-help nil
+ icicle-special-candidate nil
+ icicle-user-plain-dot nil
+ icicle-whole-candidate nil
+ invisible nil)
+ bmk)
+ (when (boundp 'icicle-candidate-properties-alist) ; Multi-completion indexes + text props.
+ (dolist (entry icicle-candidate-properties-alist)
+ (put-text-property 0 len (car (cadr entry)) nil bmk)))))))
+ (if copy (mapcar #'copy-sequence new-list) new-list)))
+
+(defun bmkp-maybe-unpropertize-string (string &optional copy)
+ "Strip properties from STRING.
+Return the unpropertized STRING.
+Non-nil optional arg COPY means return a copy of the unpropertized
+STRING. (STRING is modified before the copy is made.)
+
+Do nothing in Emacs 21 or later or if
+`bmkp-propertize-bookmark-names-flag' is non-nil. In these cases,
+just return STRING unmodified."
+ (unless (and (> emacs-major-version 20) ; Emacs 21+. Cannot just use (boundp 'print-circle).
+ bmkp-propertize-bookmark-names-flag)
+ (set-text-properties 0 (length string) nil string)
+ (when copy (setq string (copy-sequence string))))
+ string)
+
+;; This is a general command. It is in this file because it uses macro `bmkp-define-sort-command'
+;; and it is used mainly in the bookmark list display.
+;;;###autoload (autoload 'bmkp-define-tags-sort-command "bookmark+")
+(defun bmkp-define-tags-sort-command (tags &optional msg-p) ; Bound to `T s' in bookmark list
+ "Define a command to sort bookmarks in the bookmark list by tags.
+Hit `RET' to enter each tag, then hit `RET' again after the last tag.
+
+The new command sorts first by the first tag in TAGS, then by the
+second, and so on.
+
+Besides sorting for these specific tags, any bookmark that has a tag
+sorts before one that has no tags. Otherwise, sorting is by bookmark
+name, alphabetically.
+
+The name of the new command is `bmkp-bmenu-sort-' followed by the
+specified tags, in order, separated by hyphens (`-'). E.g., for TAGS
+\(\"alpha\" \"beta\"), the name is `bmkp-bmenu-sort-alpha-beta'.
+
+If you use this function non-interactively, be sure to load library
+`bookmark+-mac.el' first."
+ (interactive
+ (progn (or (condition-case nil ; Load `bookmark+-mac.el' when called interactively.
+ (load-library "bookmark+-mac") ; Use load-library to ensure latest .elc.
+ (error nil))
+ (require 'bookmark+-mac))
+ (list (bmkp-read-tags-completing) 'MSG)))
+ (let ((sort-order (concat "tags-" (mapconcat #'identity tags "-")))
+ (doc-string (read-string "Doc string for command: "))
+ (comparer ())
+ def)
+ (dolist (tag tags)
+ (push `(lambda (b1 b2)
+ (let ((tags1 (bmkp-get-tags b1))
+ (tags2 (bmkp-get-tags b2)))
+ (cond ((and (assoc-default ,tag tags1 nil t)
+ (assoc-default ,tag tags2 nil t)) nil)
+ ((assoc-default ,tag tags1 nil t) '(t))
+ ((assoc-default ,tag tags2 nil t) '(nil))
+ ((and tags1 tags2) nil)
+ (tags1 '(t))
+ (tags2 '(nil))
+ (t nil))))
+ comparer))
+ (setq comparer (nreverse comparer)
+ comparer (list comparer 'bmkp-alpha-p))
+ (eval (setq def (macroexpand `(bmkp-define-sort-command ,sort-order ,comparer ,doc-string))))
+ (with-current-buffer (find-file-noselect bmkp-bmenu-commands-file)
+ (goto-char (point-max))
+ (let ((print-length nil)
+ (print-level nil)
+ (print-circle bmkp-propertize-bookmark-names-flag)
+ (print-gensym bmkp-propertize-bookmark-names-flag)
+ (version-control (case bookmark-version-control
+ ((nil) nil)
+ (never 'never)
+ (nospecial version-control)
+ (t t)))
+ (require-final-newline t)
+ (errorp nil))
+ (pp def (current-buffer))
+ (insert "\n")
+ (condition-case nil
+ (write-file bmkp-bmenu-commands-file)
+ (file-error (setq errorp t) (error "CANNOT WRITE FILE `%s'" bmkp-bmenu-commands-file)))
+ (kill-buffer (current-buffer))
+ (when (and msg-p (not errorp))
+ (message "Defined and saved command `%s'" (concat "bmkp-bmenu-sort-" sort-order)))))))
+
+;;;###autoload (autoload 'bmkp-bmenu-relocate-marked "bookmark+")
+(defun bmkp-bmenu-relocate-marked (directory &optional include-omitted-p msgp)
+ ; Bound to `M-R' in bookmark list
+ "Relocate target files of all (visible) bookmarks that are marked `>'.
+You are prompted for the relocation target directory.
+Return the number of bookmarks relocated to DIRECTORY.
+
+Omitted bookmarks are excluded, by default. With a prefix arg, any
+that are marked are included.
+
+Non-interactively, non-nil MSG-P means display messages."
+ (interactive (list (funcall (if (fboundp 'read-directory-name)
+ #'read-directory-name
+ #'read-file-name)
+ "Relocate targets of marked bookmarks to directory: "
+ default-directory default-directory)
+ current-prefix-arg
+ 'MSGP))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((count 0)
+ file)
+ (dolist (bmk (bmkp-sort-omit (bmkp-bmenu-marked-or-this-or-all nil include-omitted-p)))
+ (when (and (setq file (bookmark-get-filename bmk))
+ (not (equal file bmkp-non-file-filename)))
+ (setq file (file-name-nondirectory file)
+ count (1+ count))
+ (bookmark-set-filename bmk (expand-file-name file directory))
+ (setq bookmark-alist-modification-count
+ (1+ bookmark-alist-modification-count))))
+ (when (bookmark-time-to-save-p) (bookmark-save))
+ (bookmark-bmenu-surreptitiously-rebuild-list)
+ (when msgp
+ (if (> count 0)
+ (message "Relocated %d bookmark%s" count (if (= 1 count) "" "s"))
+ (message "No bookmarks relocated")))
+ count))
+
+;;;###autoload (autoload 'bmkp-copy-bookmark "bookmark+")
+(defalias 'bmkp-bmenu-copy-bookmark 'bmkp-bmenu-clone-bookmark)
+;;;###autoload (autoload 'bmkp-bmenu-clone-bookmark "bookmark+")
+(defun bmkp-bmenu-clone-bookmark (&optional arg confirm-overwrite-p) ; Bound to `M-n' in bookmark list
+ "Create a duplicate copy named of the bookmark under the cursor.
+The clone name is the same as that bookmark, but with \"<2>\" appended.
+With a prefix arg you are instead prompted for the clone name."
+ (interactive "P\np")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let* ((orig (bookmark-bmenu-bookmark))
+ ;; Remove any `bmkp-full-record' property from name.
+ (_IGNORE (remove-text-properties 0 (length orig) '(bmkp-full-record nil) orig))
+ (default (concat orig "<2>"))
+ (new (if arg
+ (bmkp-completing-read-lax "Clone name" default)
+ default)))
+ (while (equal orig new)
+ (setq new (bmkp-completing-read-lax "Clone name (must be different)" default)))
+ ;; Remove any `bmkp-full-record' property from name.
+ (remove-text-properties 0 (length new) '(bmkp-full-record nil) new)
+ (bmkp-clone-bookmark orig new confirm-overwrite-p)))
+
+;;;###autoload (autoload 'bmkp-bmenu-edit-bookmark-name-and-location "bookmark+")
+(defun bmkp-bmenu-edit-bookmark-name-and-location (&optional internalp) ; Bound to `r' in bookmark list
+ "Edit the bookmark under the cursor: its name and location.
+With a prefix argument, edit the complete bookmark record (the
+internal, Lisp form)."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (let ((bmk-name (bookmark-bmenu-bookmark)))
+ (if internalp
+ (bmkp-edit-bookmark-record bmk-name)
+ (let* ((new-data (bmkp-edit-bookmark-name-and-location bmk-name))
+ (new-name (car new-data)))
+ (if (not new-data) (message "No changes made") (bmkp-refresh-menu-list new-name))))))
+
+;;;###autoload (autoload 'bmkp-bmenu-edit-tags "bookmark+")
+(defun bmkp-bmenu-edit-tags () ; Bound to `T e' in bookmark list
+ "Edit the tags of the bookmark under the cursor.
+The edited value must be a list each of whose elements is either a
+string or a cons whose key is a string."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (bmkp-edit-tags (bookmark-bmenu-bookmark)))
+
+;;;###autoload (autoload 'bmkp-bmenu-edit-bookmark-record "bookmark+")
+(defun bmkp-bmenu-edit-bookmark-record () ; Bound to `e' in bookmark list
+ "Edit the full record (the Lisp sexp) for the bookmark under the cursor.
+When you finish editing, use `\\[bmkp-edit-bookmark-record-send]'.
+The current bookmark list is then updated to reflect your edits."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bookmark-bmenu-ensure-position)
+ (bmkp-edit-bookmark-record (setq bmkp-edit-bookmark-orig-record (bookmark-bmenu-bookmark))))
+
+;;;###autoload (autoload 'bmkp-bmenu-edit-marked "bookmark+")
+(defun bmkp-bmenu-edit-marked (&optional allp include-omitted-p) ; Bound to `E' in bookmark list
+ "Edit the full records (the Lisp sexps) of the marked bookmarks.
+If no bookmarks are marked then mark the bookmark on the current line,
+and edit its record.
+
+When you finish editing, use `\\[bmkp-edit-bookmark-records-send]'.
+The current bookmark list is then updated to reflect your edits.
+
+If no bookmark is marked, edit the bookmark of the current line.
+
+With a non-negative prefix arg, edit all bookmark records.
+
+Omitted bookmarks are excluded, by default. With a negative prefix
+arg, any that are marked are included."
+ (interactive (list (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (< (prefix-numeric-value current-prefix-arg) 0))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (setq bmkp-last-bmenu-bookmark (bookmark-bmenu-bookmark))
+ ;; No marked bookmarks. Mark this bookmark, so that `C-c C-c' in edit buffer will find it.
+ ;; Do this before we copy and strip full-bookmark property from name, because `bookmark-bmenu-mark'
+ ;; propertizes the name.
+ (unless bmkp-bmenu-marked-bookmarks (bookmark-bmenu-mark))
+ (let ((bufname "*Edit Marked Bookmarks*")
+ (copied-bmks (mapcar (lambda (bmk)
+ (setq bmk (copy-sequence bmk)) ; Shallow copy
+ (let ((bname (bmkp-bookmark-name-from-record bmk)))
+ ;; Strip properties from name.
+ (set-text-properties 0 (length bname) nil bname))
+ bmk)
+ (bmkp-bmenu-marked-or-this-or-all allp include-omitted-p))))
+ (unless copied-bmks (error "No marked bookmarks"))
+ (setq bmkp-edit-bookmark-records-number (length copied-bmks))
+ (bmkp-with-output-to-plain-temp-buffer bufname
+ (princ (substitute-command-keys
+ (concat ";; Edit the Lisp records for the marked bookmarks.\n;;\n"
+ ";; DO NOT CHANGE THE ORDER of the bookmarks in this buffer.\n"
+ ";; DO NOT DELETE any of them.\n;;\n"
+ ";; Type \\<bmkp-edit-bookmark-records-mode-map>\
+`\\[bmkp-edit-bookmark-records-send]' when done.\n;;\n")))
+ ;; $$$$$$ (let ((print-circle t)) (pp copied-bmks)) ; $$$$$$ Should not really be needed now.
+ (pp copied-bmks)
+ (with-current-buffer bufname
+ (goto-char (point-min))
+ (buffer-enable-undo)))
+ (pop-to-buffer bufname)
+ (with-current-buffer (get-buffer bufname) (bmkp-edit-bookmark-records-mode))))
+
+(defun bmkp-bmenu-propertize-item (bookmark start end)
+ "Propertize text in buffer from START to END, indicating bookmark type.
+This propertizes the name of BOOKMARK.
+Also give this region the property `bmkp-bookmark-name' with as value
+the name of BOOKMARK as a propertized string.
+
+The propertized string has property `bmkp-full-record' with value
+BOOKMARK, which is the full bookmark record, with the string as its
+car.
+
+Return the propertized string (the bookmark name)."
+ (setq bookmark (bmkp-get-bookmark bookmark))
+ (let* ((bookmark-name (bmkp-bookmark-name-from-record bookmark))
+ (buffp (bmkp-get-buffer-name bookmark))
+
+ (filep (bookmark-get-filename bookmark))
+ (sudop (and filep (boundp 'tramp-file-name-regexp)
+ (bmkp-string-match-p tramp-file-name-regexp filep)
+ (bmkp-string-match-p bmkp-su-or-sudo-regexp filep))))
+ ;; Put the full bookmark itself on string `bookmark-name' as property `bmkp-full-record'.
+ ;; Then put that string on the name in the buffer text as property `bmkp-bookmark-name'.
+ (put-text-property 0 (length bookmark-name) 'bmkp-full-record bookmark bookmark-name)
+ (put-text-property start end 'bmkp-bookmark-name bookmark-name)
+ ;; Add faces, mouse face, and tooltips, to characterize the bookmark type.
+ (add-text-properties
+ start end
+ (cond ((bookmark-prop-get bookmark 'file-handler) ; `file-handler' bookmark
+ (append (bmkp-face-prop 'bmkp-file-handler)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Invoke the `file-handler' for this bookmark")))
+ ((bmkp-sequence-bookmark-p bookmark) ; Sequence bookmark
+ (append (bmkp-face-prop 'bmkp-sequence)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Invoke the bookmarks in this sequence")))
+ ((bmkp-function-bookmark-p bookmark) ; Function bookmark
+ (append (bmkp-face-prop 'bmkp-function)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Invoke this function bookmark")))
+ ((bmkp-variable-list-bookmark-p bookmark) ; Variable-list bookmark
+ (append (bmkp-face-prop 'bmkp-variable-list)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Invoke this variable-list bookmark")))
+ ((bmkp-bookmark-list-bookmark-p bookmark) ; Bookmark-list bookmark
+ (append (bmkp-face-prop 'bmkp-bookmark-list)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Invoke this bookmark-list bookmark")))
+ ((bmkp-snippet-bookmark-p bookmark) ; Snippet bookmark
+ (append (bmkp-face-prop 'bmkp-snippet)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Jump to this snippet bookmark")))
+ ((bmkp-desktop-bookmark-p bookmark) ; Desktop bookmark
+ (append (bmkp-face-prop 'bmkp-desktop)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Jump to this desktop bookmark")))
+ ((bmkp-bookmark-file-bookmark-p bookmark) ; Bookmark-file bookmark
+ (append (bmkp-face-prop 'bmkp-bookmark-file)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Load this bookmark's bookmark file")))
+ ((bmkp-non-invokable-bookmark-p bookmark) ; Non-invokable bookmark
+ (append (bmkp-face-prop 'bmkp-no-jump)
+ '(help-echo "You CANNOT JUMP to this bookmark")))
+ ((bmkp-icicles-search-hits-bookmark-p bookmark) ; Icicles search hits bookmark
+ (append (bmkp-face-prop 'bmkp-no-jump)
+ '(help-echo "You can use this only during Icicles search, NOT HERE")))
+ ((bmkp-info-bookmark-p bookmark) ; Info bookmark
+ (append (bmkp-face-prop 'bmkp-info)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Jump to this Info bookmark")))
+ ((bmkp-man-bookmark-p bookmark) ; Man bookmark
+ (append (bmkp-face-prop 'bmkp-man)
+ '(mouse-face highlight follow-link t
+ help-echo (format "mouse-2 Goto `man' page"))))
+ ((bmkp-gnus-bookmark-p bookmark) ; Gnus bookmark
+ (append (bmkp-face-prop 'bmkp-gnus)
+ '(mouse-face highlight follow-link t
+ help-echo "mouse-2: Jump to this Gnus bookmark")))
+ ((bmkp-url-bookmark-p bookmark) ; URL bookmark
+ (append (bmkp-face-prop 'bmkp-url)
+ `(mouse-face highlight follow-link t
+ help-echo (format "mouse-2: Jump to URL `%s'" ,filep))))
+ ((and sudop (not (bmkp-root-or-sudo-logged-p))) ; Root/sudo not logged in
+ (append (bmkp-face-prop 'bmkp-su-or-sudo)
+ `(mouse-face highlight follow-link t
+ help-echo (format "mouse-2: Jump to (visit) file `%s'" ,filep))))
+ ;; Test for remoteness before any other tests of the file itself
+ ;; (e.g. `file-exists-p'), so Tramp does not prompt for a password etc.
+ ((and filep (bmkp-file-remote-p filep) (not sudop)) ; Remote file (ssh, ftp)
+ (append (bmkp-face-prop 'bmkp-remote-file)
+ `(mouse-face highlight follow-link t
+ help-echo (format "mouse-2: Jump to (visit) remote file `%s'" ,filep))))
+ ((and filep ; Local directory or local Dired buffer (could be wildcards)
+ (or (file-directory-p filep) (bmkp-dired-bookmark-p bookmark)))
+ (append (bmkp-face-prop 'bmkp-local-directory)
+ `(mouse-face highlight follow-link t
+ help-echo (format "mouse-2: Dired directory `%s'" ,filep))))
+ ((and filep (file-exists-p filep) ; Local file with region
+ (bmkp-region-bookmark-p bookmark))
+ (append (bmkp-face-prop 'bmkp-local-file-with-region)
+ `(mouse-face highlight follow-link t
+ help-echo (format "mouse-2: Activate region in file `%s'" ,filep))))
+ ((and filep (file-exists-p filep)) ; Local file without region
+ (append (bmkp-face-prop 'bmkp-local-file-without-region)
+ `(mouse-face highlight follow-link t
+ help-echo (format "mouse-2: Jump to (visit) file `%s'" ,filep))))
+ ; Existing buffer, including for a file bookmark if the file buffer has not yet been saved.
+ ((and buffp (get-buffer buffp))
+ (append (bmkp-face-prop 'bmkp-buffer)
+ `(mouse-face highlight follow-link t
+ help-echo (format "mouse-2: Jump to buffer `%s'" ,buffp))))
+ ((or (not filep) (equal filep bmkp-non-file-filename)) ; Non-file, and no existing buffer.
+ (append (bmkp-face-prop 'bmkp-non-file)
+ `(mouse-face highlight follow-link t
+ help-echo (format "mouse-2: Create buffer `%s' and jump to it" ,buffp))))
+ ((and filep (not (file-exists-p filep))) ; Local-file bookmark, but no such file exists.
+ (bmkp-face-prop 'bmkp-no-local))
+ (t (append (bmkp-face-prop 'bmkp-bad-bookmark)
+ `(mouse-face highlight follow-link t
+ help-echo (format "BAD BOOKMARK (maybe): `%s'" ,filep))))))
+ bookmark-name))
+
+;;;###autoload (autoload 'bmkp-bmenu-quit "bookmark+")
+(defun bmkp-bmenu-quit () ; Bound to `q' in bookmark list
+ "Quit the bookmark list (aka \"menu list\").
+If `bmkp-bmenu-state-file' is non-nil, then save the state, to be
+restored the next time the bookmark list is shown. Otherwise, reset
+the internal lists that record menu-list markings."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (if (not bmkp-bmenu-state-file)
+ (setq bmkp-bmenu-marked-bookmarks ()
+ bmkp-bmenu-before-hide-marked-alist ()
+ bmkp-bmenu-before-hide-unmarked-alist ())
+ (when (interactive-p) (message "Saving bookmark-list display state..."))
+ (bmkp-save-menu-list-state)
+ (when (interactive-p) (message "Saving bookmark-list display state...done"))
+ (setq bmkp-bmenu-first-time-p t))
+ (quit-window))
+
+(defun bmkp-bmenu-goto-bookmark-named (name)
+ "Go to the first bookmark whose name matches NAME (a string).
+If NAME has non-nil property `bmkp-full-record' then go to the
+bookmark it indicates. Otherwise, just go to the first bookmark with
+the same name."
+ (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (let ((full (get-text-property 0 'bmkp-full-record name)))
+ (while (and (not (eobp))
+ (not (if full
+ (equal full (get-text-property 0 'bmkp-full-record (bookmark-bmenu-bookmark)))
+ (equal name (bookmark-bmenu-bookmark)))))
+ (forward-line 1)))
+ (bookmark-bmenu-ensure-position)) ; Just in case we fall off the end.
+
+;; This is a general function. It is in this file because it is used only by the bmenu code.
+(defun bmkp-bmenu-barf-if-not-in-menu-list ()
+ "Raise an error if current buffer is not `*Bookmark List*'."
+ (unless (derived-mode-p 'bookmark-bmenu-mode)
+ (error "You can only use this command in buffer `*Bookmark List*'")))
+
+(defun bmkp-face-prop (value)
+ "Return a list with elements `face' or `font-lock-face' and VALUE.
+Starting with Emacs 22, the first element is `font-lock-face'."
+ (list (if (> emacs-major-version 21) 'font-lock-face 'face) value))
+
+(when (or (> emacs-major-version 24) ; Emacs bug #12867 was partially fixed for Emacs 24.3+.
+ (and (= emacs-major-version 24) (> emacs-minor-version 2)))
+ (defun bmkp-bmenu-mode-line-string ()
+ "Show, in mode line, information about the current bookmark-list display.
+The information includes the sort order and the number of marked,
+flagged (for deletion), tagged, temporary, annotated, and modified
+bookmarks currently shown.
+
+For each number indication:
+ If the current line has the indicator (e.g. mark, flag) and there are
+ others with the same indicator listed after it, then show `N/M',
+ where N is the number indicated through the current line and M is the
+ total number indicated."
+ (let* ((regexp-> "^>")
+ (regexp-D "^D")
+ (regexp-t "^.t")
+ (regexp-X "^..X")
+ (regexp-a "^..a")
+ (regexp-* "^...\\*")
+ (nb-> (count-matches regexp-> (point-min) (point-max)))
+ (nb-D (count-matches regexp-D (point-min) (point-max)))
+ (nb-t (count-matches regexp-t (point-min) (point-max)))
+ (nb-X (count-matches regexp-X (point-min) (point-max)))
+ (nb-a (count-matches regexp-a (point-min) (point-max)))
+ (nb-* (count-matches regexp-* (point-min) (point-max)))
+ (text-sort (propertize
+ (concat "sorting " (bmkp-sorting-description (bmkp-current-sort-order)))
+ 'face 'bmkp-heading))
+ regexp)
+ (let ((desc "")
+ nb)
+ (dolist (mk '(?> ?D ?t ?a ?X ?*))
+ (setq nb (symbol-value (intern (format "nb-%c" mk)))
+ regexp (symbol-value (intern (format "regexp-%c" mk)))
+ desc (concat
+ desc
+ (and (> nb 0)
+ (propertize
+ (format
+ "%s%d%c"
+ (save-excursion
+ (forward-line 0)
+ (if (bmkp-looking-at-p (concat regexp ".*"))
+ (format "%d/" (1+ (count-matches regexp (point-min) (point))))
+ ""))
+ nb mk)
+ 'face (intern (format "bmkp-%c-mark" mk))))
+ (and (> nb 0) " "))))
+ (format "%s%s" desc text-sort))))
+
+ (defun bmkp-bmenu-mode-line () ; This works, but it shows the line number also.
+ "Set the mode line for buffer `*Bookmark List*'."
+ (condition-case nil
+ (progn
+ (set (make-local-variable 'mode-name) '(:eval (bmkp-bmenu-mode-line-string)))
+ ;; It seems that the line number must be present, and not invisible, for dynamic updating
+ ;; of the mode line when you move the cursor among lines. Moving it way off to the right
+ ;; effectively gets rid of it (ugly hack). See Emacs bug #12867.
+ (set (make-local-variable 'mode-line-position) '("%360l (line)")) ; Move it off the screen.
+ (set (make-local-variable 'mode-line-format)
+ '(("" mode-name "\t" mode-line-buffer-identification mode-line-position))))
+ (error nil))))
+
+(when (fboundp 'org-add-link-type)
+ (org-add-link-type "bookmark" 'bookmark-jump)
+ (org-add-link-type "bookmark-other-win" 'bookmark-jump-other-window)
+ (add-hook 'org-store-link-functions 'bmkp-bmenu-store-org-link 'APPEND)
+ (defun bmkp-bmenu-store-org-link ()
+ "Store a link to this bookmark for insertion in an Org-mode buffer.
+If you use a numeric prefix arg with `\\[org-store-link]' then the
+bookmark will be jumped to in the same window. Without a numeric
+prefix arg, the link will use another window. The link type is
+`bookmark' or `bookmark-other-win', respectively."
+ (require 'org)
+ (and (derived-mode-p 'bookmark-bmenu-mode)
+ (let* ((other-win (and current-prefix-arg (not (consp current-prefix-arg))))
+ (bmk (bookmark-bmenu-bookmark))
+ (link (format "bookmark%s:%s" (if other-win "-other-win" "") bmk))
+ (bmk-desc (format "Bookmark: %s" bmk)))
+ (org-store-link-props :type "bookmark" :link link :description bmk-desc)))))
+
+
+;;(@* "Sorting - Commands")
+;; *** Sorting - Commands ***
+
+;;;###autoload (autoload 'bmkp-bmenu-change-sort-order-repeat "bookmark+")
+(defun bmkp-bmenu-change-sort-order-repeat (arg) ; Bound to `s s'... in bookmark list
+ "Cycle to the next sort order.
+With a prefix arg, reverse current sort order.
+This is a repeatable version of `bmkp-bmenu-change-sort-order'."
+ (interactive "P")
+ (require 'repeat)
+ (bmkp-repeat-command 'bmkp-bmenu-change-sort-order))
+
+;;;###autoload (autoload 'bmkp-bmenu-change-sort-order "bookmark+")
+(defun bmkp-bmenu-change-sort-order (&optional arg)
+ "Cycle to the next sort order.
+With a prefix arg, reverse the current sort order."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (setq bmkp-sort-orders-for-cycling-alist (delq nil bmkp-sort-orders-for-cycling-alist))
+ (if arg
+ (bmkp-reverse-sort-order)
+ (let ((curr-bmk (bookmark-bmenu-bookmark))
+ next-order)
+ (let ((orders (mapcar #'car bmkp-sort-orders-for-cycling-alist)))
+ (setq next-order (or (cadr (member (bmkp-current-sort-order) orders)) (car orders))
+ bmkp-sort-comparer (cdr (assoc next-order bmkp-sort-orders-for-cycling-alist))))
+ (message "Sorting...")
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk ; Put cursor back on the right line.
+ (bmkp-bmenu-goto-bookmark-named curr-bmk))
+ (when (interactive-p) (bmkp-msg-about-sort-order next-order)))))
+
+;; This is a general command. It is in this file because it is used only by the bmenu code.
+;;;###autoload (autoload 'bmkp-reverse-sort-order "bookmark+")
+(defun bmkp-reverse-sort-order () ; Bound to `s r' in bookmark list
+ "Reverse the current bookmark sort order.
+If you combine this with \\<bookmark-bmenu-mode-map>\
+`\\[bmkp-reverse-multi-sort-order]', then see the doc for that command."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (setq bmkp-reverse-sort-p (not bmkp-reverse-sort-p))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk ; Put cursor back on the right line.
+ (bmkp-bmenu-goto-bookmark-named curr-bmk)))
+ (when (interactive-p) (bmkp-msg-about-sort-order (bmkp-current-sort-order))))
+
+;; This is a general command. It is in this file because it is used only by the bmenu code.
+;;;###autoload (autoload 'bmkp-reverse-multi-sort-order "bookmark+")
+(defun bmkp-reverse-multi-sort-order () ; Bound to `s C-r' in bookmark list
+ "Reverse the application of multi-sorting predicates.
+These are the PRED predicates described for option
+`bmkp-sort-comparer'.
+
+This reverses the order in which the predicates are tried, and it
+also complements the truth value returned by each predicate.
+
+For example, if the list of multi-sorting predicates is (p1 p2 p3),
+then the predicates are tried in the order: p3, p2, p1. And if a
+predicate returns true, `(t)', then the effect is as if it returned
+false, `(nil)', and vice versa.
+
+The use of multi-sorting predicates tends to group bookmarks, with the
+first predicate corresponding to the first bookmark group etc.
+
+The effect of \\<bookmark-bmenu-mode-map>`\\[bmkp-reverse-multi-sort-order]' is \
+roughly as follows:
+
+ - without also `\\[bmkp-reverse-sort-order]', it reverses the bookmark order in each \
+group
+
+ - combined with `\\[bmkp-reverse-sort-order]', it reverses the order of the bookmark
+ groups, but not the bookmarks within a group
+
+This is a rough description. The actual behavior can be complex,
+because of how each predicate is defined. If this description helps
+you, fine. If not, just experiment and see what happens. \;-)
+
+Remember that ordinary `\\[bmkp-reverse-sort-order]' reversal on its own is \
+straightforward.
+If you find `\\[bmkp-reverse-multi-sort-order]' confusing or not helpful, then do not \
+use it."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (setq bmkp-reverse-multi-sort-p (not bmkp-reverse-multi-sort-p))
+ (let ((curr-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P)
+ (when curr-bmk ; Put cursor back on the right line.
+ (bmkp-bmenu-goto-bookmark-named curr-bmk)))
+ (when (interactive-p) (bmkp-msg-about-sort-order (bmkp-current-sort-order))))
+
+
+
+;; The ORDER of the macro calls here defines the REVERSE ORDER of
+;; `bmkp-sort-orders-alist'. The first here is thus also the DEFAULT sort order.
+;; Entries are traversed by `s s'..., in `bmkp-sort-orders-alist' order.
+
+(bmkp-define-sort-command ; Bound to `s k' in bookmark list (`k' for "kind")
+ "by bookmark type" ; `bmkp-bmenu-sort-by-bookmark-type'
+ ((bmkp-info-node-name-cp bmkp-url-cp bmkp-gnus-cp bmkp-local-file-type-cp bmkp-handler-cp)
+ bmkp-alpha-p)
+ "Sort bookmarks by type: Info, URL, Gnus, files, other (by handler name).")
+
+(bmkp-define-sort-command ; Bound to `s u' in bookmark list
+ "by url" ; `bmkp-bmenu-sort-by-url'
+ ((bmkp-url-cp) bmkp-alpha-p)
+ "Sort URL bookmarks alphabetically by their URL/filename.
+When two bookmarks are not comparable this way, compare them by
+bookmark name.")
+
+;; $$$$$$ Not used now.
+;; (bmkp-define-sort-command ; Bound to `s w 3' in bookmark list
+;; "by W3M url" ; `bmkp-bmenu-sort-by-w3m-url'
+;; ((bmkp-w3m-cp) bmkp-alpha-p)
+;; "Sort W3M bookmarks alphabetically by their URL/filename.
+;; When two bookmarks are not comparable this way, compare them by
+;; bookmark name.")
+
+;; (when (fboundp 'bmkp-eww-cp)
+;; ;; $$$$$$ Not used now.
+;; ;; (bmkp-define-sort-command ; Bound to `s w e' in bookmark list
+;; ;; "by EWW url" ; `bmkp-bmenu-sort-by-w3m-url'
+;; ;; ((bmkp-eww-cp) bmkp-alpha-p)
+;; ;; "Sort EWW bookmarks alphabetically by their URL/filename.
+;; ;; When two bookmarks are not comparable this way, compare them by
+;; ;; bookmark name.")
+;; )
+
+(bmkp-define-sort-command ; Bound to `s g' in bookmark list
+ "by Gnus thread" ; `bmkp-bmenu-sort-by-Gnus-thread'
+ ((bmkp-gnus-cp) bmkp-alpha-p)
+ "Sort Gnus bookmarks by group, then by article, then by message.
+When two bookmarks are not comparable this way, compare them by
+bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s i' in bookmark list
+ "by Info node name" ; `bmkp-bmenu-sort-by-Info-node-name'
+ ((bmkp-info-node-name-cp) bmkp-alpha-p)
+ "Sort Info bookmarks by manual (file) name, then node name, then position.
+When two bookmarks are not comparable this way, compare them by
+bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s I' in bookmark list
+ "by Info position" ; `bmkp-bmenu-sort-by-Info-position'
+ ((bmkp-info-position-cp) bmkp-alpha-p)
+ "Sort Info bookmarks by manual (file) name, then position (order in book).
+When two bookmarks are not comparable this way, compare them by
+bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s f u' in bookmark list
+ "by last local file update" ; `bmkp-bmenu-sort-by-last-local-file-update'
+ ((bmkp-local-file-updated-more-recently-cp) bmkp-alpha-p)
+ "Sort bookmarks by last local file update time.
+Sort a local file before a remote file, and a remote file before other
+bookmarks. Otherwise, sort by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s f d' in bookmark list
+ "by last local file access" ; `bmkp-bmenu-sort-by-last-local-file-access'
+ ((bmkp-local-file-accessed-more-recently-cp) bmkp-alpha-p)
+ "Sort bookmarks by last local file access time.
+A local file sorts before a remote file, which sorts before other
+bookmarks. Otherwise, sort by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s f s' in bookmark list
+ "by local file size" ; `bmkp-bmenu-sort-by-local-file-size'
+ ((bmkp-local-file-size-cp) bmkp-alpha-p)
+ "Sort bookmarks by local file size.
+A local file sorts before a remote file, which sorts before other
+bookmarks. Otherwise, sort by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s f n' in bookmark list
+ "by file name" ; `bmkp-bmenu-sort-by-file-name'
+ ((bmkp-file-alpha-cp) bmkp-alpha-p)
+ "Sort bookmarks by file name.
+When two bookmarks are not comparable by file name, compare them by
+bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s f k' in bookmark list (`k' for "kind")
+ "by local file type" ; `bmkp-bmenu-sort-by-local-file-type'
+ ((bmkp-local-file-type-cp) bmkp-alpha-p)
+ "Sort bookmarks by local file type: file, symlink, directory.
+A local file sorts before a remote file, which sorts before other
+bookmarks. Otherwise, sort by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s D' in bookmark list
+ "flagged before unflagged" ; `bmkp-bmenu-sort-flagged-before-unflagged'
+ ((bmkp-flagged-cp) bmkp-alpha-p)
+ "Sort bookmarks by putting flagged for deletion before unflagged.
+Otherwise alphabetize by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s *' in bookmark list
+ "modified before unmodified" ; `bmkp-bmenu-sort-modified-before-unmodified'
+ ((bmkp-modified-cp) bmkp-alpha-p)
+ "Sort bookmarks by putting modified before unmodified (saved).
+Otherwise alphabetize by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s >' in bookmark list
+ "marked before unmarked" ; `bmkp-bmenu-sort-marked-before-unmarked'
+ ((bmkp-marked-cp) bmkp-alpha-p)
+ "Sort bookmarks by putting marked before unmarked.
+Otherwise alphabetize by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s 0' (zero) in bookmark list
+ "by creation time" ; `bmkp-bmenu-sort-by-creation-time'
+ ((bmkp-bookmark-creation-cp) bmkp-alpha-p)
+ "Sort bookmarks by the time of their creation.
+When one or both of the bookmarks does not have a `created' entry),
+compare them by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s a' in bookmark list
+ "annotated before unannotated" ; `bmkp-bmenu-sort-annotated-before-unannotated'
+ ((bmkp-annotated-cp) bmkp-alpha-p)
+ "Sort bookmarks by putting annotated before unannotated.
+Otherwise alphabetize by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s b' in bookmark list
+ "by last buffer or file access" ; `bmkp-bmenu-sort-by-last-buffer-or-file-access'
+ ((bmkp-buffer-last-access-cp bmkp-local-file-accessed-more-recently-cp)
+ bmkp-alpha-p)
+ "Sort bookmarks by last buffer access or last local file access.
+Sort a bookmark accessed more recently before one accessed less
+recently or not accessed. Sort a bookmark to an existing buffer
+before a local file bookmark. When two bookmarks are not comparable
+by such critera, sort them by bookmark name. (In particular, sort
+remote-file bookmarks by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s v' in bookmark list
+ "by bookmark visit frequency" ; `bmkp-bmenu-sort-by-bookmark-visit-frequency'
+ ((bmkp-visited-more-cp) bmkp-alpha-p)
+ "Sort bookmarks by the number of times they were visited as bookmarks.
+When two bookmarks are not comparable by visit frequency, compare them
+by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s d' in bookmark list
+ "by last bookmark access" ; `bmkp-bmenu-sort-by-last-bookmark-access'
+ ((bmkp-bookmark-last-access-cp) bmkp-alpha-p)
+ "Sort bookmarks by the time of their last visit as bookmarks.
+When two bookmarks are not comparable by visit time, compare them
+by bookmark name.")
+
+(bmkp-define-sort-command ; Bound to `s n' in bookmark list
+ "by bookmark name" ; `bmkp-bmenu-sort-by-bookmark-name'
+ bmkp-alpha-p
+ "Sort bookmarks by bookmark name, respecting `case-fold-search'.")
+
+(bmkp-define-sort-command ; Bound to `s t' in bookmark list
+ "tagged before untagged" ; `bmkp-bmenu-sort-tagged-before-untagged'
+ ((bmkp-tagged-cp) bmkp-alpha-p)
+ "Sort bookmarks by putting tagged before untagged.
+Otherwise alphabetize by bookmark name.")
+
+;; This is a general option. It is in this file because it is used mainly by the bmenu code.
+;; Its definitions MUST COME AFTER the calls to macro `bmkp-define-sort-command'.
+;; Otherwise, they won't pick up a populated `bmkp-sort-orders-alist'.
+(when (> emacs-major-version 20)
+ (defcustom bmkp-sort-orders-for-cycling-alist (copy-sequence bmkp-sort-orders-alist)
+ "*Alist of sort orders used for cycling via `s s'...
+This is a subset of the complete list of available sort orders,
+`bmkp-sort-orders-alist'. This lets you cycle among fewer sort
+orders, if there are some that you do not use often.
+
+See the doc for `bmkp-sort-orders-alist', for the structure of
+this value."
+ :type '(alist
+ :key-type (choice :tag "Sort order" string symbol)
+ :value-type (choice
+ (const :tag "None (do not sort)" nil)
+ (function :tag "Sorting Predicate")
+ (list :tag "Sorting Multi-Predicate"
+ (repeat (function :tag "Component Predicate"))
+ (choice
+ (const :tag "None" nil)
+ (function :tag "Final Predicate")))))
+ :group 'bookmark-plus))
+
+(unless (> emacs-major-version 20) ; Emacs 20: custom type `alist' doesn't exist.
+ (defcustom bmkp-sort-orders-for-cycling-alist (copy-sequence bmkp-sort-orders-alist)
+ "*Alist of sort orders used for cycling via `s s'...
+This is a subset of the complete list of available sort orders,
+`bmkp-sort-orders-alist'. This lets you cycle among fewer sort
+orders, if there are some that you do not use often.
+
+See the doc for `bmkp-sort-orders-alist', for the structure of this
+value."
+ :type '(repeat
+ (cons
+ (choice :tag "Sort order" string symbol)
+ (choice
+ (const :tag "None (do not sort)" nil)
+ (function :tag "Sorting Predicate")
+ (list :tag "Sorting Multi-Predicate"
+ (repeat (function :tag "Component Predicate"))
+ (choice
+ (const :tag "None" nil)
+ (function :tag "Final Predicate"))))))
+ :group 'bookmark-plus))
+
+
+;;(@* "Other Bookmark+ Functions (`bmkp-*')")
+;; *** Other Bookmark+ Functions (`bmkp-*') ***
+
+;;;###autoload (autoload 'bmkp-bmenu-show-this-annotation+move-down "bookmark+")
+(defun bmkp-bmenu-show-this-annotation+move-down (&optional n) ; Bound to `M-down' in bookmark list
+ "Move down N lines in bookmark-list display and show annotation, if any."
+ (interactive "p")
+ (bmkp-bmenu-kill-annotation)
+ (forward-line n)
+ (bookmark-bmenu-show-annotation 'MSGP))
+
+;;;###autoload (autoload 'bmkp-bmenu-show-this-annotation+move-up "bookmark+")
+(defun bmkp-bmenu-show-this-annotation+move-up (&optional n) ; Bound to `M-up' in bookmark list
+ "Move up N lines in bookmark-list display and show annotation, if any."
+ (interactive "p")
+ (bmkp-bmenu-kill-annotation)
+ (forward-line (- n))
+ (bookmark-bmenu-show-annotation 'MSGP))
+
+(defun bmkp-bmenu-kill-annotation (&optional bookmark-name)
+ "Kill annotation buffer, if any, for BOOKMARK-NAME.
+If BOOKMARK-NAME is nil, use the bookmark of the current line.
+Return non-nil only if there was such an annotation buffer."
+ (let ((ann-buf (get-buffer (format "*`%s' Annotation*"
+ (or bookmark-name (bookmark-bmenu-bookmark))))))
+ (when ann-buf (kill-buffer ann-buf))))
+
+;;;###autoload (autoload 'bmkp-bmenu-describe-this+move-down "bookmark+")
+(defun bmkp-bmenu-describe-this+move-down (&optional defn) ; Bound to `C-down' in bookmark list
+ "Move to next line in bookmark-list display and describe the bookmark.
+With a prefix argument, show the internal definition of the bookmark."
+ (interactive "P")
+ (forward-line 1)
+ (bmkp-bmenu-describe-this-bookmark))
+
+;;;###autoload (autoload 'bmkp-bmenu-describe-this+move-up "bookmark+")
+(defun bmkp-bmenu-describe-this+move-up (&optional defn) ; Bound to `C-up' in bookmark list
+ "Move to previous line in bookmark-list display and describe the bookmark.
+With a prefix argument, show the internal definition of the bookmark."
+ (interactive "P")
+ (forward-line -1)
+ (bmkp-bmenu-describe-this-bookmark))
+
+;;;###autoload (autoload 'bmkp-bmenu-describe-this-bookmark "bookmark+")
+(defun bmkp-bmenu-describe-this-bookmark (&optional defn) ; Bound to `C-h RET' in bookmark list
+ "Describe bookmark of current line.
+With a prefix argument, show the internal definition of the bookmark."
+ (interactive "P")
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (save-selected-window (if defn
+ (bmkp-describe-bookmark-internals (bookmark-bmenu-bookmark))
+ (bmkp-describe-bookmark (bookmark-bmenu-bookmark)))))
+
+;;;###autoload (autoload 'bmkp-bmenu-describe-marked "bookmark+")
+(defun bmkp-bmenu-describe-marked (&optional defn include-omitted-p) ; Bound to `C-h >' in bookmark list
+ "Describe the marked bookmarks, in the current sort order.
+If no bookmark is marked, act on the bookmark of the current line.
+
+With a non-negative prefix argument, show the internal definitions.
+
+Omitted bookmarks are excluded, by default. With a non-positive
+prefix arg, any that are marked are included."
+ (interactive (list (and current-prefix-arg (>= (prefix-numeric-value current-prefix-arg) 0))
+ (and current-prefix-arg (<= (prefix-numeric-value current-prefix-arg) 0))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (help-setup-xref (list #'bmkp-bmenu-describe-marked) (interactive-p))
+ (bmkp-with-help-window "*Help*"
+ (dolist (bmk (bmkp-sort-omit (bmkp-bmenu-marked-or-this-or-all nil include-omitted-p)))
+ (if defn
+ (let* ((bname (bmkp-bookmark-name-from-record bmk))
+ (print-circle bmkp-propertize-bookmark-names-flag) ; For `pp-to-string'
+ (print-gensym bmkp-propertize-bookmark-names-flag) ; For `pp-to-string'
+ (print-length nil) ; For `pp-to-string'
+ (print-level nil) ; For `pp-to-string'
+ (help-text (format "%s\n%s\n\n%s"
+ bname (make-string (length bname) ?-) (pp-to-string bmk))))
+ (princ help-text) (terpri))
+ (princ (bmkp-bookmark-description bmk)) (terpri)))))
+
+(defun bmkp-bmenu-get-marked-files ()
+ "Return a list of the file names of the marked bookmarks.
+Marked bookmarks that have no associated file are ignored."
+ (let ((files ()))
+ (dolist (bmk bmkp-bmenu-marked-bookmarks)
+ (when (bmkp-file-bookmark-p bmk) (push (bookmark-get-filename bmk) files)))
+ files))
+
+(defun bmkp-bmenu-marked-or-this-or-all (&optional allp include-omitted-p)
+ "Return the marked bookmarks or the current-line bookmark if none marked.
+Non-nil ALLP means return all bookmarks: `bookmark-alist'.
+Do not include marked bookmarks that are omitted, unless optional arg
+INCLUDE-OMITTED-P is non-nil. INCLUDE-OMITTED-P has no effect if none
+are marked or ALLP is non-nil."
+ (if allp
+ bookmark-alist
+ (or (if include-omitted-p
+ (bmkp-marked-bookmarks-only)
+ (bmkp-remove-if #'bmkp-omitted-bookmark-p (bmkp-marked-bookmarks-only)))
+ (and (bookmark-bmenu-bookmark) (list (bmkp-get-bookmark (bookmark-bmenu-bookmark)))))))
+
+;;(@* "Keymaps")
+;;; Keymaps ----------------------------------------------------------
+
+;; `bookmark-bmenu-mode-map'
+
+(when (< emacs-major-version 21)
+ (define-key bookmark-bmenu-mode-map (kbd "RET") 'bookmark-bmenu-this-window))
+(define-key bookmark-bmenu-mode-map "\M-~" 'bmkp-toggle-saving-bookmark-file)
+(define-key bookmark-bmenu-mode-map (kbd "C-M-~") 'bmkp-toggle-saving-menu-list-state)
+(define-key bookmark-bmenu-mode-map "." 'bmkp-bmenu-show-all)
+(define-key bookmark-bmenu-mode-map ">" 'bmkp-bmenu-toggle-show-only-marked)
+(define-key bookmark-bmenu-mode-map "<" 'bmkp-bmenu-toggle-show-only-unmarked)
+(define-key bookmark-bmenu-mode-map (kbd "M-<DEL>") 'bmkp-bmenu-unmark-all)
+(define-key bookmark-bmenu-mode-map "-" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "->" 'bmkp-bmenu-omit/unomit-marked)
+(define-key bookmark-bmenu-mode-map "-S" 'bmkp-bmenu-show-only-omitted-bookmarks)
+(define-key bookmark-bmenu-mode-map "-U" 'bmkp-unomit-all)
+(define-key bookmark-bmenu-mode-map "=" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "=bM" 'bmkp-bmenu-mark-specific-buffer-bookmarks)
+(define-key bookmark-bmenu-mode-map "=fM" 'bmkp-bmenu-mark-specific-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "=bS" 'bmkp-bmenu-show-only-specific-buffer-bookmarks)
+(define-key bookmark-bmenu-mode-map "=fS" 'bmkp-bmenu-show-only-specific-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "%" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "%m" 'bmkp-bmenu-regexp-mark)
+(define-key bookmark-bmenu-mode-map "*" nil) ; For Emacs 20
+(when (< emacs-major-version 21)
+ (define-key bookmark-bmenu-mode-map "*m" 'bookmark-bmenu-mark))
+(define-key bookmark-bmenu-mode-map "#" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "#M" 'bmkp-bmenu-mark-autonamed-bookmarks)
+(define-key bookmark-bmenu-mode-map "#S" 'bmkp-bmenu-show-only-autonamed-bookmarks)
+;; `a' is `bookmark-bmenu-show-annotation' in vanilla Emacs.
+;; `A' is `bookmark-bmenu-show-all-annotations' in vanilla Emacs.
+;; `e' is `bookmark-bmenu-edit-annotation' in vanilla Emacs.
+(define-key bookmark-bmenu-mode-map "a" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "aa" 'bookmark-bmenu-show-annotation)
+(define-key bookmark-bmenu-mode-map "aA" 'bookmark-bmenu-show-all-annotations)
+(define-key bookmark-bmenu-mode-map "ae" 'bookmark-bmenu-edit-annotation)
+(define-key bookmark-bmenu-mode-map "a>" 'bmkp-bmenu-edit-annotations-for-marked)
+(define-key bookmark-bmenu-mode-map "A" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "AM" 'bmkp-bmenu-mark-autofile-bookmarks)
+(define-key bookmark-bmenu-mode-map "AS" 'bmkp-bmenu-show-only-autofile-bookmarks)
+(define-key bookmark-bmenu-mode-map "B" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "BM" 'bmkp-bmenu-mark-non-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "BS" 'bmkp-bmenu-show-only-non-file-bookmarks)
+(define-key bookmark-bmenu-mode-map (kbd "M-n") 'bmkp-bmenu-clone-bookmark)
+(define-key bookmark-bmenu-mode-map (kbd "C-c C-c") 'bmkp-bmenu-define-command)
+(define-key bookmark-bmenu-mode-map (kbd "C-c C-S-c") 'bmkp-bmenu-define-full-snapshot-command)
+(define-key bookmark-bmenu-mode-map (kbd "C-c C-j") 'bmkp-bmenu-define-jump-marked-command)
+(define-key bookmark-bmenu-mode-map "d" 'bmkp-bmenu-flag-for-deletion)
+(define-key bookmark-bmenu-mode-map "D" 'bmkp-bmenu-delete-marked)
+(define-key bookmark-bmenu-mode-map "\C-d" 'bmkp-bmenu-flag-for-deletion-backwards)
+(define-key bookmark-bmenu-mode-map "\M-d" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "\M-d>" 'bmkp-bmenu-dired-marked)
+(define-key bookmark-bmenu-mode-map "\M-d\M-m" 'bmkp-bmenu-mark-dired-bookmarks)
+(define-key bookmark-bmenu-mode-map "\M-d\M-s" 'bmkp-bmenu-show-only-dired-bookmarks)
+;; `e' is `bookmark-bmenu-edit-annotation' in vanilla Emacs.
+(define-key bookmark-bmenu-mode-map "e" 'bmkp-bmenu-edit-bookmark-record)
+(define-key bookmark-bmenu-mode-map "E" 'bmkp-bmenu-edit-marked)
+(define-key bookmark-bmenu-mode-map "F" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "FM" 'bmkp-bmenu-mark-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "FS" 'bmkp-bmenu-show-only-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "g" 'bmkp-bmenu-refresh-menu-list)
+(define-key bookmark-bmenu-mode-map "G" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "GM" 'bmkp-bmenu-mark-gnus-bookmarks)
+(define-key bookmark-bmenu-mode-map "GS" 'bmkp-bmenu-show-only-gnus-bookmarks)
+(if (fboundp 'command-remapping)
+ (define-key bookmark-bmenu-mode-map [remap describe-mode] 'bmkp-bmenu-mode-status-help)
+ ;; In Emacs < 22, the `substitute-...' affects only `?', not `C-h m', so we add it separately.
+ (substitute-key-definition 'describe-mode 'bmkp-bmenu-mode-status-help bookmark-bmenu-mode-map)
+ (define-key bookmark-bmenu-mode-map "\C-hm" 'bmkp-bmenu-mode-status-help))
+(define-key bookmark-bmenu-mode-map (kbd "C-h >") 'bmkp-bmenu-describe-marked)
+(define-key bookmark-bmenu-mode-map (kbd "C-h RET") 'bmkp-bmenu-describe-this-bookmark)
+(define-key bookmark-bmenu-mode-map (kbd "C-h C-<return>") 'bmkp-bmenu-describe-this-bookmark)
+(define-key bookmark-bmenu-mode-map (kbd "C-<down>") 'bmkp-bmenu-describe-this+move-down)
+(define-key bookmark-bmenu-mode-map (kbd "C-<up>") 'bmkp-bmenu-describe-this+move-up)
+(define-key bookmark-bmenu-mode-map (kbd "M-<down>") 'bmkp-bmenu-show-this-annotation+move-down)
+(define-key bookmark-bmenu-mode-map (kbd "M-<up>") 'bmkp-bmenu-show-this-annotation+move-up)
+(define-key bookmark-bmenu-mode-map (kbd "M-<return>") 'bmkp-bmenu-w32-open)
+(define-key bookmark-bmenu-mode-map [M-mouse-2] 'bmkp-bmenu-w32-open-with-mouse)
+(when (featurep 'bookmark+-lit)
+ (define-key bookmark-bmenu-mode-map "H" nil) ; For Emacs 20
+ (define-key bookmark-bmenu-mode-map "H+" 'bmkp-bmenu-set-lighting)
+ (define-key bookmark-bmenu-mode-map "H>+" 'bmkp-bmenu-set-lighting-for-marked)
+ (define-key bookmark-bmenu-mode-map "H>H" 'bmkp-bmenu-light-marked)
+ (define-key bookmark-bmenu-mode-map "HH" 'bmkp-bmenu-light)
+ (define-key bookmark-bmenu-mode-map "HM" 'bmkp-bmenu-mark-lighted-bookmarks)
+ (define-key bookmark-bmenu-mode-map "HS" 'bmkp-bmenu-show-only-lighted-bookmarks)
+ (define-key bookmark-bmenu-mode-map "H>U" 'bmkp-bmenu-unlight-marked)
+ (define-key bookmark-bmenu-mode-map "HU" 'bmkp-bmenu-unlight))
+(define-key bookmark-bmenu-mode-map "i" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "iM" 'bmkp-bmenu-mark-icicles-search-hits-bookmarks)
+(define-key bookmark-bmenu-mode-map "iS" 'bmkp-bmenu-show-only-icicles-search-hits-bookmarks)
+(define-key bookmark-bmenu-mode-map "I" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "IM" 'bmkp-bmenu-mark-info-bookmarks)
+(define-key bookmark-bmenu-mode-map "IS" 'bmkp-bmenu-show-only-info-bookmarks)
+(define-key bookmark-bmenu-mode-map "\M-I" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "\M-I\M-M" 'bmkp-bmenu-mark-image-bookmarks)
+(define-key bookmark-bmenu-mode-map "\M-I\M-S" 'bmkp-bmenu-show-only-image-bookmarks)
+
+;; Prefix `j' and `J' bindings are made in `bookmark+-key.el', by binding `bmkp-jump(-other-window)-map'.
+
+(define-key bookmark-bmenu-mode-map "k" 'bmkp-bmenu-flag-for-deletion)
+(define-key bookmark-bmenu-mode-map "K" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "KM" 'bmkp-bmenu-mark-desktop-bookmarks)
+(define-key bookmark-bmenu-mode-map "KS" 'bmkp-bmenu-show-only-desktop-bookmarks)
+(define-key bookmark-bmenu-mode-map "L" 'bmkp-switch-bookmark-file-create)
+(define-key bookmark-bmenu-mode-map [(control shift ?l)] 'bookmark-bmenu-locate) ; `C-L' (aka `C-S-l')
+(define-key bookmark-bmenu-mode-map "\M-l" 'bmkp-bmenu-load-marked-bookmark-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "\M-L" 'bmkp-temporary-bookmarking-mode)
+(define-key bookmark-bmenu-mode-map "M" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "MM" 'bmkp-bmenu-mark-man-bookmarks)
+(define-key bookmark-bmenu-mode-map "MS" 'bmkp-bmenu-show-only-man-bookmarks)
+(define-key bookmark-bmenu-mode-map "\M-m" 'bmkp-bmenu-mark-all)
+(define-key bookmark-bmenu-mode-map "N" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "NM" 'bmkp-bmenu-mark-non-invokable-bookmarks)
+(define-key bookmark-bmenu-mode-map "NS" 'bmkp-bmenu-show-only-non-invokable-bookmarks)
+(define-key bookmark-bmenu-mode-map "O" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "OM" 'bmkp-bmenu-mark-orphaned-local-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "OS" 'bmkp-bmenu-show-only-orphaned-local-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "P" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "PA" 'bmkp-bmenu-filter-annotation-incrementally)
+(define-key bookmark-bmenu-mode-map "PB" 'bmkp-bmenu-filter-bookmark-name-incrementally)
+(define-key bookmark-bmenu-mode-map "PF" 'bmkp-bmenu-filter-file-name-incrementally)
+(define-key bookmark-bmenu-mode-map "PT" 'bmkp-bmenu-filter-tags-incrementally)
+(define-key bookmark-bmenu-mode-map "q" 'bmkp-bmenu-quit)
+(define-key bookmark-bmenu-mode-map "\M-q" 'bmkp-bmenu-query-replace-marked-bookmarks-regexp)
+(define-key bookmark-bmenu-mode-map "Q" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "QM" 'bmkp-bmenu-mark-function-bookmarks)
+(define-key bookmark-bmenu-mode-map "QS" 'bmkp-bmenu-show-only-function-bookmarks)
+(define-key bookmark-bmenu-mode-map "r" 'bmkp-bmenu-edit-bookmark-name-and-location)
+(define-key bookmark-bmenu-mode-map "R" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "RM" 'bmkp-bmenu-mark-region-bookmarks)
+(define-key bookmark-bmenu-mode-map "RS" 'bmkp-bmenu-show-only-region-bookmarks)
+(define-key bookmark-bmenu-mode-map "\M-r" 'bookmark-bmenu-relocate) ; `R' in Emacs
+(define-key bookmark-bmenu-mode-map "\M-R" 'bmkp-bmenu-relocate-marked)
+(define-key bookmark-bmenu-mode-map "S" 'bookmark-bmenu-save) ; `s' in Emacs
+(define-key bookmark-bmenu-mode-map "s" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "s>" 'bmkp-bmenu-sort-marked-before-unmarked)
+(define-key bookmark-bmenu-mode-map "s*" 'bmkp-bmenu-sort-modified-before-unmodified)
+(define-key bookmark-bmenu-mode-map "s0" 'bmkp-bmenu-sort-by-creation-time)
+(define-key bookmark-bmenu-mode-map "sa" 'bmkp-bmenu-sort-annotated-before-unannotated)
+(define-key bookmark-bmenu-mode-map "sb" 'bmkp-bmenu-sort-by-last-buffer-or-file-access)
+(define-key bookmark-bmenu-mode-map "sd" 'bmkp-bmenu-sort-by-last-bookmark-access)
+(define-key bookmark-bmenu-mode-map "sD" 'bmkp-bmenu-sort-flagged-before-unflagged)
+(define-key bookmark-bmenu-mode-map "sfd" 'bmkp-bmenu-sort-by-last-local-file-access)
+(define-key bookmark-bmenu-mode-map "sfk" 'bmkp-bmenu-sort-by-local-file-type)
+(define-key bookmark-bmenu-mode-map "sfn" 'bmkp-bmenu-sort-by-file-name)
+(define-key bookmark-bmenu-mode-map "sfs" 'bmkp-bmenu-sort-by-local-file-size)
+(define-key bookmark-bmenu-mode-map "sfu" 'bmkp-bmenu-sort-by-last-local-file-update)
+(define-key bookmark-bmenu-mode-map "sg" 'bmkp-bmenu-sort-by-Gnus-thread)
+(define-key bookmark-bmenu-mode-map "si" 'bmkp-bmenu-sort-by-Info-node-name)
+(define-key bookmark-bmenu-mode-map "sI" 'bmkp-bmenu-sort-by-Info-position)
+(define-key bookmark-bmenu-mode-map "sk" 'bmkp-bmenu-sort-by-bookmark-type)
+(define-key bookmark-bmenu-mode-map "sn" 'bmkp-bmenu-sort-by-bookmark-name)
+(define-key bookmark-bmenu-mode-map "sr" 'bmkp-reverse-sort-order)
+(define-key bookmark-bmenu-mode-map "s\C-r" 'bmkp-reverse-multi-sort-order)
+(define-key bookmark-bmenu-mode-map "ss" 'bmkp-bmenu-change-sort-order-repeat)
+(define-key bookmark-bmenu-mode-map "st" 'bmkp-bmenu-sort-tagged-before-untagged)
+(define-key bookmark-bmenu-mode-map "su" 'bmkp-bmenu-sort-by-url)
+(define-key bookmark-bmenu-mode-map "sv" 'bmkp-bmenu-sort-by-bookmark-visit-frequency)
+
+;; Not done yet.
+;; ;; (define-key bookmark-bmenu-mode-map "sw" nil) ; For Emacs20
+;; ;; (define-key bookmark-bmenu-mode-map "swe" 'bmkp-bmenu-sort-by-eww-url)
+;; ;; (define-key bookmark-bmenu-mode-map "sw3" 'bmkp-bmenu-sort-by-w3m-url)
+
+(when (> emacs-major-version 22) ; Emacs 23+
+ (define-key bookmark-bmenu-mode-map (kbd "M-s a C-s") 'bmkp-bmenu-isearch-marked-bookmarks)
+ (define-key bookmark-bmenu-mode-map (kbd "M-s a M-C-s") 'bmkp-bmenu-isearch-marked-bookmarks-regexp))
+(define-key bookmark-bmenu-mode-map (kbd "M-s a M-s") 'bmkp-bmenu-search-marked-bookmarks-regexp)
+(define-key bookmark-bmenu-mode-map "T" nil) ; For Emacs20
+(define-key bookmark-bmenu-mode-map "T>+" 'bmkp-bmenu-add-tags-to-marked)
+(define-key bookmark-bmenu-mode-map "T>-" 'bmkp-bmenu-remove-tags-from-marked)
+(define-key bookmark-bmenu-mode-map "T>e" 'bmkp-bmenu-edit-marked)
+(define-key bookmark-bmenu-mode-map "T>l" 'bmkp-bmenu-list-tags-of-marked)
+(define-key bookmark-bmenu-mode-map "T>p" 'bmkp-bmenu-paste-add-tags-to-marked)
+(define-key bookmark-bmenu-mode-map "T>q" 'bmkp-bmenu-paste-replace-tags-for-marked)
+(define-key bookmark-bmenu-mode-map "T>v" 'bmkp-bmenu-set-tag-value-for-marked)
+(define-key bookmark-bmenu-mode-map "T>\C-y" 'bmkp-bmenu-paste-add-tags-to-marked)
+(define-key bookmark-bmenu-mode-map "T0" 'bmkp-remove-all-tags)
+(define-key bookmark-bmenu-mode-map "T+" 'bmkp-add-tags)
+(define-key bookmark-bmenu-mode-map "T-" 'bmkp-remove-tags)
+(define-key bookmark-bmenu-mode-map "Tc" 'bmkp-bmenu-copy-tags)
+(define-key bookmark-bmenu-mode-map "Td" 'bmkp-remove-tags-from-all)
+(define-key bookmark-bmenu-mode-map "Te" 'bmkp-bmenu-edit-tags)
+(define-key bookmark-bmenu-mode-map "Tl" 'bmkp-list-all-tags)
+(define-key bookmark-bmenu-mode-map "Tm*" 'bmkp-bmenu-mark-bookmarks-tagged-all)
+(define-key bookmark-bmenu-mode-map "Tm%" 'bmkp-bmenu-mark-bookmarks-tagged-regexp)
+(define-key bookmark-bmenu-mode-map "Tm+" 'bmkp-bmenu-mark-bookmarks-tagged-some)
+(define-key bookmark-bmenu-mode-map "Tm~*" 'bmkp-bmenu-mark-bookmarks-tagged-not-all)
+(define-key bookmark-bmenu-mode-map "Tm~+" 'bmkp-bmenu-mark-bookmarks-tagged-none)
+(define-key bookmark-bmenu-mode-map "Tp" 'bmkp-bmenu-paste-add-tags)
+(define-key bookmark-bmenu-mode-map "Tq" 'bmkp-bmenu-paste-replace-tags)
+(define-key bookmark-bmenu-mode-map "Tr" 'bmkp-rename-tag)
+(define-key bookmark-bmenu-mode-map "Ts" 'bmkp-define-tags-sort-command)
+(define-key bookmark-bmenu-mode-map "TS" 'bmkp-bmenu-show-only-tagged-bookmarks)
+(define-key bookmark-bmenu-mode-map "TU" 'bmkp-bmenu-show-only-untagged-bookmarks)
+(define-key bookmark-bmenu-mode-map "Tu*" 'bmkp-bmenu-unmark-bookmarks-tagged-all)
+(define-key bookmark-bmenu-mode-map "Tu%" 'bmkp-bmenu-unmark-bookmarks-tagged-regexp)
+(define-key bookmark-bmenu-mode-map "Tu+" 'bmkp-bmenu-unmark-bookmarks-tagged-some)
+(define-key bookmark-bmenu-mode-map "Tu~*" 'bmkp-bmenu-unmark-bookmarks-tagged-not-all)
+(define-key bookmark-bmenu-mode-map "Tu~+" 'bmkp-bmenu-unmark-bookmarks-tagged-none)
+(define-key bookmark-bmenu-mode-map "Tv" 'bmkp-bmenu-set-tag-value)
+(define-key bookmark-bmenu-mode-map "T\M-w" 'bmkp-bmenu-copy-tags)
+(define-key bookmark-bmenu-mode-map "T\C-y" 'bmkp-bmenu-paste-add-tags)
+(define-key bookmark-bmenu-mode-map "\M-t" 'bookmark-bmenu-toggle-filenames) ; `t' in Emacs
+(define-key bookmark-bmenu-mode-map "t" 'bmkp-bmenu-toggle-marks)
+(define-key bookmark-bmenu-mode-map "U" 'bmkp-bmenu-unmark-all)
+(define-key bookmark-bmenu-mode-map "\M-u" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "\M-u\M-m" 'bmkp-bmenu-mark-url-bookmarks)
+(define-key bookmark-bmenu-mode-map "\M-u\M-s" 'bmkp-bmenu-show-only-url-bookmarks)
+(define-key bookmark-bmenu-mode-map "v" 'bmkp-bmenu-w32-jump-to-marked)
+(define-key bookmark-bmenu-mode-map "V" nil) ; For Emacs20
+(define-key bookmark-bmenu-mode-map "VM" 'bmkp-bmenu-mark-variable-list-bookmarks)
+(define-key bookmark-bmenu-mode-map "VS" 'bmkp-bmenu-show-only-variable-list-bookmarks)
+(define-key bookmark-bmenu-mode-map "\M-o" 'bmkp-bmenu-w32-jump-to-marked)
+(define-key bookmark-bmenu-mode-map "W" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "W3" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "W3M" 'bmkp-bmenu-mark-w3m-bookmarks)
+(define-key bookmark-bmenu-mode-map "W3S" 'bmkp-bmenu-show-only-w3m-bookmarks)
+
+(when (fboundp 'bmkp-bmenu-mark-eww-bookmarks) ; Emacs 25+
+ (define-key bookmark-bmenu-mode-map "WEM" 'bmkp-bmenu-mark-eww-bookmarks)
+ (define-key bookmark-bmenu-mode-map "WES" 'bmkp-bmenu-show-only-eww-bookmarks)
+ )
+(define-key bookmark-bmenu-mode-map "w" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "wM" 'bmkp-bmenu-mark-snippet-bookmarks)
+(define-key bookmark-bmenu-mode-map "wS" 'bmkp-bmenu-show-only-snippet-bookmarks)
+(define-key bookmark-bmenu-mode-map "X" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "XM" 'bmkp-bmenu-mark-temporary-bookmarks)
+(define-key bookmark-bmenu-mode-map "XS" 'bmkp-bmenu-show-only-temporary-bookmarks)
+(define-key bookmark-bmenu-mode-map "\M-X" 'bmkp-bmenu-toggle-marked-temporary/savable)
+(define-key bookmark-bmenu-mode-map "\C-\M-X" 'bmkp-bmenu-toggle-temporary)
+(define-key bookmark-bmenu-mode-map "Y" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "YM" 'bmkp-bmenu-mark-bookmark-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "YS" 'bmkp-bmenu-show-only-bookmark-file-bookmarks)
+(define-key bookmark-bmenu-mode-map "Y>" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "Y>+" 'bmkp-bmenu-copy-marked-to-bookmark-file)
+(define-key bookmark-bmenu-mode-map "Y>-" 'bmkp-bmenu-move-marked-to-bookmark-file)
+(define-key bookmark-bmenu-mode-map "Y>0" 'bmkp-bmenu-create-bookmark-file-from-marked)
+(define-key bookmark-bmenu-mode-map "Z" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "ZM" 'bmkp-bmenu-mark-bookmark-list-bookmarks)
+(define-key bookmark-bmenu-mode-map "ZS" 'bmkp-bmenu-show-only-bookmark-list-bookmarks)
+
+
+;;; `Bookmark+' menu-bar menu in `*Bookmark List*'
+
+(defvar bmkp-bmenu-menubar-menu (make-sparse-keymap "Bookmark+") "`Boomark+' menu-bar menu.")
+(define-key bookmark-bmenu-mode-map [menu-bar bmkp]
+ (cons "Bookmark+" bmkp-bmenu-menubar-menu))
+
+;; Top level
+(define-key bmkp-bmenu-menubar-menu [bmkp-bmenu-quit]
+ '(menu-item "Quit" bmkp-bmenu-quit
+ :help "Quit the bookmark list, saving its state and the current set of bookmarks"))
+(define-key bmkp-bmenu-menubar-menu [bmkp-list-defuns-in-commands-file]
+ '(menu-item "List User-Defined Bookmark Commands" bmkp-list-defuns-in-commands-file
+ :help "List the functions defined in `bmkp-bmenu-commands-file'"))
+(define-key bmkp-bmenu-menubar-menu [bmkp-bmenu-describe-marked]
+ '(menu-item "Describe Marked Bookmarks" bmkp-bmenu-describe-marked
+ :help "Describe the marked bookmarks. With `C-u' show internal format."))
+(define-key bmkp-bmenu-menubar-menu [bmkp-bmenu-describe-this-bookmark]
+ '(menu-item "Describe This Bookmark" bmkp-bmenu-describe-this-bookmark
+ :help "Describe this line's bookmark. With `C-u' show internal format."))
+(define-key bmkp-bmenu-menubar-menu [bmkp-bmenu-mode-status-help]
+ '(menu-item "Current Status, Mode Help" bmkp-bmenu-mode-status-help :keys "?"
+ :help "Describe `*Bookmark List*' and show its current status"))
+
+(define-key bmkp-bmenu-menubar-menu [top-sep7] '("--")) ; ------------
+(define-key bmkp-bmenu-menubar-menu [bmkp-revert-bookmark-file]
+ '(menu-item "Revert to Saved..." bmkp-revert-bookmark-file
+ :help "Revert to bookmarks in current bookmark file, as last saved" :keys "C-u g"))
+(define-key bmkp-bmenu-menubar-menu [bmkp-bmenu-refresh-menu-list]
+ '(menu-item "Refresh to Current" bmkp-bmenu-refresh-menu-list
+ :help "Update display to reflect current bookmark list (`C-u': revert from file)"))
+
+(define-key bmkp-bmenu-menubar-menu [top-sep6] '("--")) ; ------------
+(define-key bmkp-bmenu-menubar-menu [bmkp-save-menu-list-state]
+ '(menu-item "Save Display State..." bmkp-save-menu-list-state
+ :help "Save the current bookmark-list display state to `bmkp-bmenu-state-file'"
+ :enable (and (not bmkp-bmenu-first-time-p) bmkp-bmenu-state-file)))
+(define-key bmkp-bmenu-menubar-menu [bookmark-write]
+ '(menu-item "Save As..." bookmark-write
+ :help "Write the current set of bookmarks to a file whose name you enter"))
+(define-key bmkp-bmenu-menubar-menu [bookmark-bmenu-save]
+ '(menu-item "Save" bookmark-bmenu-save
+ :help "Save the current set of bookmarks to the current bookmark file"
+ :enable (> bookmark-alist-modification-count 0)))
+
+(define-key bmkp-bmenu-menubar-menu [top-sep5] '("--")) ; ----------
+(define-key bmkp-bmenu-menubar-menu [bmkp-bmenu-relocate-marked]
+ '(menu-item "Relocate Marked..." bmkp-bmenu-relocate-marked
+ :help "Relocate the marked bookmarks to a directory"))
+
+(define-key bmkp-bmenu-menubar-menu [top-sep4] '("--")) ; ----------
+(define-key bmkp-bmenu-menubar-menu [bmkp-make-function-bookmark]
+ '(menu-item "New Function Bookmark..." bmkp-make-function-bookmark
+ :help "Create a bookmark that will invoke FUNCTION when \"jumped\" to"))
+(define-key bmkp-bmenu-menubar-menu [bmkp-bmenu-make-sequence-from-marked]
+ '(menu-item "New Sequence Bookmark from Marked..." bmkp-bmenu-make-sequence-from-marked
+ :help "Create or update a sequence bookmark from the visible marked bookmarks"))
+(define-key bmkp-bmenu-menubar-menu [bmkp-bmenu-clone-bookmark]
+ '(menu-item "Clone (Duplicate) This Bookmark" bmkp-bmenu-clone-bookmark
+ :help "Clone this bookmark. (`\\[bmkp-bmenu-edit-bookmark-record]' to edit.)"))
+
+(define-key bmkp-bmenu-menubar-menu [top-sep3] '("--")) ; ----------
+(define-key bmkp-bmenu-menubar-menu [bmkp-choose-navlist-from-bookmark-list]
+ '(menu-item "Set Navlist from Bookmark-List Bookmark..." bmkp-choose-navlist-from-bookmark-list
+ :help "Set the navigation list from a bookmark-list bookmark"))
+(define-key bmkp-bmenu-menubar-menu [bmkp-choose-navlist-of-type]
+ '(menu-item "Set Navlist to Bookmarks of Type..." bmkp-choose-navlist-of-type
+ :help "Set the navigation list to the bookmarks of a certain type"))
+
+(define-key bmkp-bmenu-menubar-menu [top-sep2] '("--")) ; ----------
+
+(defvar bmkp-bmenu-define-command-menu (make-sparse-keymap "Define Command")
+ "`Define Command' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [define-command]
+ (cons "Define Command" bmkp-bmenu-define-command-menu))
+
+(defvar bmkp-bmenu-bookmark-file-menu (make-sparse-keymap "Bookmark File")
+ "`Bookmark File' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [bookmark-file] (cons "Bookmark File" bmkp-bmenu-bookmark-file-menu))
+
+(when (or (featurep 'bookmark+-lit)
+ (and (fboundp 'diredp-highlight-autofiles-mode) (featurep 'highlight)))
+ (defvar bmkp-bmenu-highlight-menu (make-sparse-keymap "Highlight")
+ "`Highlight' submenu for menu-bar `Bookmark+' menu.")
+ (define-key bmkp-bmenu-menubar-menu [highlight] (cons "Highlight" bmkp-bmenu-highlight-menu)))
+
+(defvar bmkp-bmenu-tags-menu (make-sparse-keymap "Tags")
+ "`Tags' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [tags] (cons "Tags" bmkp-bmenu-tags-menu))
+
+(defvar bmkp-bmenu-search-menu (make-sparse-keymap "Search")
+ "`Search' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [search] (cons "Search" bmkp-bmenu-search-menu))
+
+(defvar bmkp-bmenu-sort-menu (make-sparse-keymap "Sort")
+ "`Sort' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [sort] (cons "Sort" bmkp-bmenu-sort-menu))
+
+(defvar bmkp-bmenu-edit-menu (make-sparse-keymap "Edit")
+ "`Edit' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [edit] (cons "Edit" bmkp-bmenu-edit-menu))
+
+(defvar bmkp-bmenu-show-menu (make-sparse-keymap "Show")
+ "`Show' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [show] (cons "Show" bmkp-bmenu-show-menu))
+
+(defvar bmkp-bmenu-omit-menu (make-sparse-keymap "Omit")
+ "`Omit' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [omitting] (cons "Omit" bmkp-bmenu-omit-menu))
+
+(defvar bmkp-bmenu-mark-menu (make-sparse-keymap "Mark")
+ "`Mark' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [marking] (cons "Mark" bmkp-bmenu-mark-menu))
+
+(defvar bmkp-bmenu-delete-menu (make-sparse-keymap "Delete")
+ "`Delete' submenu for menu-bar `Bookmark+' menu.")
+(define-key bmkp-bmenu-menubar-menu [delete] (cons "Delete" bmkp-bmenu-delete-menu))
+
+(defvar bmkp-bmenu-toggle-menu (make-sparse-keymap "Toggle")
+ "`Toggle' submenu for menu-bar menus `Bookmark+' and `Bookmarks'.")
+(define-key bmkp-bmenu-menubar-menu [toggle] (cons "Toggle" bmkp-bmenu-toggle-menu))
+
+
+;;; `Define Command' submenu -----------------------------------------
+(define-key bmkp-bmenu-define-command-menu [bmkp-bmenu-define-full-snapshot-command]
+ '(menu-item "To Restore Full Bookmark-List State..." bmkp-bmenu-define-full-snapshot-command
+ :help "Define a command to restore the current bookmark-list state"))
+(define-key bmkp-bmenu-define-command-menu [bmkp-bmenu-define-command]
+ '(menu-item "To Restore Current Order and Filter..." bmkp-bmenu-define-command
+ :help "Define a command to use the current sort order, filter, and omit list"))
+(define-key bmkp-bmenu-define-command-menu [bmkp-define-tags-sort-command]
+ '(menu-item "To Sort by Specific Tags..." bmkp-define-tags-sort-command
+ :help "Define a command to sort bookmarks in the bookmark list by certain tags"))
+(define-key bmkp-bmenu-define-command-menu [bmkp-bmenu-define-jump-marked-command]
+ '(menu-item "To Jump to a Bookmark Now Marked..." bmkp-bmenu-define-jump-marked-command
+ :help "Define a command to jump to one of the bookmarks that is now marked"
+ :enable bmkp-bmenu-marked-bookmarks))
+
+
+;;; `Bookmark File' submenu ------------------------------------------
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-bmenu-set-bookmark-file-bookmark-from-marked]
+ '(menu-item "Set Bookmark-File Bookmark from Marked..."
+ bmkp-bmenu-set-bookmark-file-bookmark-from-marked
+ :help "Create a bookmark file and a bookmark for it, from the marked bookmarks"
+ :keys "C-u Y > 0"))
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-bmenu-create-bookmark-file-from-marked]
+ '(menu-item "Copy Marked to New Bookmark File..." bmkp-bmenu-create-bookmark-file-from-marked
+ :help "Create a bookmark file by copying the marked bookmarks (or current bookmark)"))
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-bmenu-copy-marked-to-bookmark-file]
+ '(menu-item "Copy Marked to Bookmark File..." bmkp-bmenu-copy-marked-to-bookmark-file
+ :help "Copy the marked bookmarks (or current bookmark) to a bookmark file"))
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-bmenu-move-marked-to-bookmark-file]
+ '(menu-item "Move Marked to Bookmark File..." bmkp-bmenu-move-marked-to-bookmark-file
+ :help "Move the marked bookmarks (or current bookmark) to a different bookmark file"))
+
+(define-key bmkp-bmenu-bookmark-file-menu [sep] '("--")) ; ------------
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-bmenu-load-marked-bookmark-file-bookmarks]
+ '(menu-item "Load Marked Bookmark-File Bookmarks..." bmkp-bmenu-load-marked-bookmark-file-bookmarks
+ :help "Load the marked bookmark-file bookmarks, in order"))
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-bmenu-load-marking-unmark-first]
+ '(menu-item "Load Bookmarks, Mark Only Those Loaded...." bmkp-bmenu-load-marking-unmark-first
+ :help "`bookmark-load', marking those loaded, unmarking others"))
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-bmenu-load-marking]
+ '(menu-item "Load Bookmarks, Mark Those Loaded...." bmkp-bmenu-load-marking
+ :help "`bookmark-load', marking bookmarks that are loaded"))
+(define-key bmkp-bmenu-bookmark-file-menu [bf-sep2] '("--")) ; ------------
+;;; (define-key bmkp-bmenu-bookmark-file-menu [bmkp-save-bookmarks-this-file/buffer]
+;;; '(menu-item "Save Bookmarks Here to File (No Switch)..." bmkp-save-bookmarks-this-file/buffer
+;;; :help "Save bookmarks defined for the current file or buffer to file"))
+;;; (define-key bmkp-bmenu-bookmark-file-menu [bmkp-switch-to-bookmark-file-this-file/buffer]
+;;; '(menu-item "Switch to Bookmarks Here..." bmkp-switch-to-bookmark-file-this-file/buffer
+;;; :help "Switch to a bookmark file with only bookmarks for this file or buffer"))
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-switch-to-last-bookmark-file]
+ '(menu-item "Switch to Last Bookmark File" bmkp-switch-to-last-bookmark-file
+ :help "Switch back to last set of bookmarks used, *replacing* current set" :keys "C-u L"))
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-switch-bookmark-file-create]
+ '(menu-item "Switch to Bookmarks..." bmkp-switch-bookmark-file-create
+ :help "Switch to another bookmark file, *replacing* the current set of bookmarks"))
+(define-key bmkp-bmenu-bookmark-file-menu [bookmark-bmenu-load]
+ '(menu-item "Load (Add) Bookmarks..." bookmark-bmenu-load
+ :help "Load additional bookmarks from a bookmark file"))
+(define-key bmkp-bmenu-bookmark-file-menu [bf-sep1] '("--")) ; ------------
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-empty-file]
+ '(menu-item "Empty Bookmark File..." bmkp-empty-file
+ :help "Empty an existing bookmark file or create a new, empty bookmark file"))
+(define-key bmkp-bmenu-bookmark-file-menu [bmkp-revert-bookmark-file]
+ '(menu-item "Revert to Saved Bookmarks..." bmkp-revert-bookmark-file
+ :help "Revert to bookmarks in current bookmark file, as last saved" :keys "C-u g"))
+
+
+;;; `Toggle' submenu -------------------------------------------------
+
+(define-key bmkp-bmenu-toggle-menu [diredp-highlight-autofiles-mode]
+ (bmkp-menu-bar-make-toggle diredp-highlight-autofiles-mode
+ diredp-highlight-autofiles-mode
+ "Autofile Highlighting in Dired"
+ "Whether to highlight autofile bookmarks in Dired us biw %s"
+ "Toggle the value of option `diredp-highlight-autofiles-mode'"
+ nil
+ :visible (and (fboundp 'diredp-highlight-autofiles-mode)
+ (featurep 'highlight))))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-guess-default-file-handler]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-guess-default-file-handler
+ bmkp-guess-default-handler-for-file-flag
+ "Guessing Default File Handler"
+ "Guessing the default handler when creating a file bookmark is now %s"
+ "Toggle the value of option `bmkp-guess-default-handler-for-file-flag'"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-auto-light-when-jump-menu]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-auto-light-when-jump-menu bmkp-auto-light-when-jump
+ "Automatic Highlighting When Jumping"
+ "Bookmark highlighting when you jump to a bookmark is now %s"
+ "Toggle the value of option `bmkp-auto-light-when-jump'"
+ (bmkp-toggle-auto-light-when-jump)
+ :visible (featurep 'bookmark+-lit)))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-auto-light-when-set-menu]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-auto-light-when-set-menu bmkp-auto-light-when-set
+ "Automatic Highlighting When Setting"
+ "Bookmark highlighting when you set a bookmark is now %s"
+ "Toggle the value of option `bmkp-auto-light-when-set'"
+ (bmkp-toggle-auto-light-when-set)
+ :visible (featurep 'bookmark+-lit)))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-prompt-for-tags]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-prompt-for-tags bmkp-prompt-for-tags-flag
+ "Prompting for Tags When Setting"
+ "Prompting for tags when you set a bookmark is now %s"
+ "Toggle the value of option `bmkp-prompt-for-tags-flag'"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-propertize-bookmark-names]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-propertize-bookmark-names bmkp-propertize-bookmark-names-flag
+ "Allowing Identical Bookmark Names"
+ "Allowing multiple bookmarks with the same name is now %s"
+ "Toggle the value of option `bmkp-propertize-bookmark-names-flag'"
+ nil
+ :visible (> emacs-major-version 20)))
+
+(define-key bmkp-bmenu-toggle-menu [sep4] '("--")) ; ------------ Jumping-behavior stuff
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-w3m-allow-multiple-buffers]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-w3m-allow-multiple-buffers bmkp-w3m-allow-multiple-buffers-flag
+ "Using Multiple Buffers for W3M"
+ "Using a new buffer when jumping to a W3M bookmark is now %s"
+ "Toggle the value of option `bmkp-w3m-allow-multiple-buffers-flag'"))
+(when (boundp 'bmkp-eww-allow-multiple-buffers-flag) ; Emacs 25+
+ (define-key bmkp-bmenu-toggle-menu [bmkp-toggle-eww-allow-multiple-buffers]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-eww-allow-multiple-buffers bmkp-eww-allow-multiple-buffers-flag
+ "Using Multiple Buffers for EWW"
+ "Using a new buffer when jumping to an EWW bookmark is now %s"
+ "Toggle the value of option `bmkp-eww-allow-multiple-buffers-flag'"))
+ )
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-showing-region-end]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-showing-region-end bmkp-show-end-of-region-flag
+ "Showing Region End"
+ "Showing the end of the region when activating is now %s"
+ "Toggle the value of option `bmkp-show-end-of-region-flag'"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-pop-to]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-pop-to bmkp-other-window-pop-to-flag
+ "Using `pop-to-buffer'"
+ "Using `pop-to-buffer' instead of `switch-to-buffer-other-window' is now %s"
+ "Toggle the value of option `bmkp-other-window-pop-to-flag'"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-auto-light-when-jump-menu]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-auto-light-when-jump-menu bmkp-auto-light-when-jump
+ "Automatic Highlighting When Jumping"
+ "Bookmark highlighting when you jump to a bookmark is now %s"
+ "Toggle the value of option `bmkp-auto-light-when-jump'"
+ (progn (bmkp-toggle-auto-light-when-jump) bmkp-auto-light-when-jump)
+ :visible (featurep 'bookmark+-lit)))
+(when (> emacs-major-version 21)
+ (define-key bmkp-bmenu-toggle-menu [bmkp-toggle-crosshairs]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-crosshairs bmkp-crosshairs-flag
+ "Crosshairs Highlighting"
+ "Highlighting bookmark location with crosshairs is now %s"
+ "Toggle the value of option `bmkp-crosshairs-flag'"
+ nil
+ :visible (featurep 'crosshairs))))
+
+(define-key bmkp-bmenu-toggle-menu [sep3] '("--")) ; ------------ Temporary bookmark stuff
+(define-key bmkp-bmenu-toggle-menu [bmkp-bmenu-toggle-marked-temporary/savable]
+ '(menu-item "Temporary/Savable (`X') for Marked" bmkp-bmenu-toggle-marked-temporary/savable
+ :help "Toggle the temporary (`X') vs. savable status of the marked bookmarks"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-temporary-bookmarking-mode]
+ (bmkp-menu-bar-make-toggle bmkp-temporary-bookmarking-mode bmkp-temporary-bookmarking-mode
+ "Temporary Bookmarking"
+ "Temporary bookmarking mode is now %s"
+ "Toggle automatically saving bookmark changes"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-autotemp-on-set]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-autotemp-on-set bmkp-autotemp-all-when-set-p
+ "Making Bookmarks Temporary When Set"
+ "Automatically making bookmarks temporary when you set them is now %s"
+ "Toggle automatically making a bookmark temporary when you set it"))
+
+(define-key bmkp-bmenu-toggle-menu [sep2] '("--")) ; ------------ List display stuff
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-bookmark-set-refreshes]
+ '(menu-item "Autorefresh for `bmkp-latest-bookmark-alist'" bmkp-toggle-bookmark-set-refreshes
+ :help "Toggle whether `bookmark-set' refreshes `bmkp-latest-bookmark-alist'"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-count-multi-mods-as-one]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-count-multi-mods-as-one bmkp-count-multi-mods-as-one-flag
+ "Counting Multiple Modifications As One"
+ "Counting multiple modifications as one is now %s"
+ "Toggle the value of option `bmkp-count-multi-mods-as-one-flag'"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-bmenu-toggle-marks]
+ '(menu-item "Marked/Unmarked" bmkp-bmenu-toggle-marks
+ :help "Unmark all marked bookmarks; mark all unmarked bookmarks"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-reverse-sort-order]
+ '(menu-item "Sort Direction" bmkp-reverse-sort-order
+ :help "Toggle the current bookmark sort direction"
+ :enable (bmkp-current-sort-order)))
+(define-key bmkp-bmenu-toggle-menu [bmkp-bmenu-toggle-show-only-unmarked]
+ '(menu-item "Showing Only Unmarked" bmkp-bmenu-toggle-show-only-unmarked
+ :help "Alternately show unmarked or all bookmarks"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-bmenu-toggle-show-only-marked]
+ '(menu-item "Showing Only Marked" bmkp-bmenu-toggle-show-only-marked
+ :help "Alternately show unmarked or all bookmarks"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-bmenu-toggle-filenames]
+ (bmkp-menu-bar-make-toggle bmkp-bmenu-toggle-filenames bookmark-bmenu-toggle-filenames
+ "Showing File Names"
+ "Showing file names is now %s"
+ "Toggle the value of option `bookmark-bmenu-toggle-filenames'"
+ (progn
+ (custom-load-symbol 'bookmark-bmenu-toggle-filenames)
+ (let ((set (or (get 'bookmark-bmenu-toggle-filenames 'custom-set)
+ 'set-default))
+ (get (or (get 'bookmark-bmenu-toggle-filenames 'custom-get)
+ 'default-value)))
+ (funcall set 'bookmark-bmenu-toggle-filenames
+ (not (funcall get 'bookmark-bmenu-toggle-filenames))))
+ (if bookmark-bmenu-toggle-filenames
+ (bookmark-bmenu-show-filenames)
+ (bookmark-bmenu-hide-filenames))
+ bookmark-bmenu-toggle-filenames)
+ :keys "M-t"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-saving-menu-list-state]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-saving-menu-list-state bmkp-bmenu-state-file
+ "Saving Display State"
+ "Ability to save bookmark list state, and autosaving, are now %s"
+ "Toggle the value of option `bmkp-bmenu-state-file'"))
+
+(define-key bmkp-bmenu-toggle-menu [sep1] '("--")) ; ------------ Automatic stuff
+(define-key bmkp-bmenu-toggle-menu [bmkp-automatic-bookmark-mode]
+ '(menu-item "Automatically Creating Bookmarks" bmkp-automatic-bookmark-mode
+ :help "Toggle the periodic automatic creation of bookmarks"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-save-desktop-before-switching]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-save-desktop-before-switching bmkp-desktop-jump-save-before-flag
+ "Autosaving the Desktop Before Switching"
+ "Autosaving the desktop before jumping to a desktop bookmark is now %s"
+ "Toggle the value of option `bmkp-desktop-jump-save-before-flag'"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-saving-relocated]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-saving-relocated bmkp-save-new-location-flag
+ "Autosaving Relocated Bookmarks"
+ "Automatically saving relocated bookmarks is now %s"
+ "Toggle the value of option `bmkp-save-new-location-flag'"))
+(define-key bmkp-bmenu-toggle-menu [bmkp-toggle-saving-bookmark-file]
+ (bmkp-menu-bar-make-toggle bmkp-toggle-saving-bookmark-file bookmark-save-flag
+ "Autosaving Bookmark File"
+ "Automatically saving the bookmark file (`bookmark-save-flag') is now %s"
+ "Toggle the value of option `bookmark-save-flag'"))
+
+
+;;; `Highlight' submenu ----------------------------------------------
+(when (boundp 'bmkp-bmenu-highlight-menu)
+ (define-key bmkp-bmenu-highlight-menu [diredp-highlight-autofiles-mode]
+ (bmkp-menu-bar-make-toggle diredp-highlight-autofiles-mode
+ diredp-highlight-autofiles-mode
+ "Toggle Autofile Highlighting in Dired"
+ "Whether to highlight autofile bookmarks in Dired us biw %s"
+ "Toggle `diredp-highlight-autofiles-mode'"
+ nil
+ :visible (and (fboundp 'diredp-highlight-autofiles-mode)
+ (featurep 'highlight))))
+ (when (featurep 'bookmark+-lit)
+ (define-key bmkp-bmenu-highlight-menu [bmkp-bmenu-show-only-lighted-bookmarks]
+ '(menu-item "Show Only Highlighted" bmkp-bmenu-show-only-lighted-bookmarks
+ :help "Display (only) highlighted bookmarks"))
+ (define-key bmkp-bmenu-highlight-menu [bmkp-bmenu-set-lighting-for-marked]
+ '(menu-item "Set Highlighting for Marked" bmkp-bmenu-set-lighting-for-marked
+ :help "Set specific highlighting for the marked bookmarks"
+ :enable bmkp-bmenu-marked-bookmarks))
+ (define-key bmkp-bmenu-highlight-menu [bmkp-bmenu-unlight-marked]
+ '(menu-item "Unhighlight Marked" bmkp-bmenu-unlight-marked
+ :help "Unhighlight the marked bookmarks"
+ :enable bmkp-bmenu-marked-bookmarks))
+ (define-key bmkp-bmenu-highlight-menu [bmkp-bmenu-light-marked]
+ '(menu-item "Highlight Marked" bmkp-bmenu-light-marked
+ :help "Highlight the marked bookmarks"
+ :enable bmkp-bmenu-marked-bookmarks))))
+
+
+;;; `Tags' submenu ---------------------------------------------------
+(define-key bmkp-bmenu-tags-menu [bmkp-list-all-tags]
+ '(menu-item "List All Tags" bmkp-list-all-tags
+ :help "List all tags used for any bookmarks (`C-u': show full, internal form)"))
+(define-key bmkp-bmenu-tags-menu [bmkp-bmenu-list-tags-of-marked]
+ '(menu-item "List Tags of Marked" bmkp-bmenu-list-tags-of-marked
+ :help "List all tags used in the marked bookmarks (`C-u': show full, internal form)"))
+(define-key bmkp-bmenu-tags-menu [bmkp-purge-notags-autofiles]
+ '(menu-item "Purge Autofiles with No Tags..." bmkp-purge-notags-autofiles
+ :help "Delete all autofile bookmarks that have no tags"))
+(define-key bmkp-bmenu-tags-menu [bmkp-untag-a-file]
+ '(menu-item "Untag a File (Remove Some)..." bmkp-untag-a-file
+ :help "Remove some tags from autofile bookmark for a file"))
+(define-key bmkp-bmenu-tags-menu [bmkp-tag-a-file]
+ '(menu-item "Tag a File (Add Some)..." bmkp-tag-a-file
+ :help "Add some tags to the autofile bookmark for a file"))
+
+(define-key bmkp-bmenu-tags-menu [tags-sep] '("--")) ; ---------------
+(define-key bmkp-bmenu-tags-menu [bmkp-rename-tag]
+ '(menu-item "Rename Tag..." bmkp-rename-tag
+ :help "Rename a tag in all bookmarks, even those not showing"))
+(define-key bmkp-bmenu-tags-menu [bmkp-bmenu-edit-marked]
+ '(menu-item "Edit Tags of Marked (Lisp)" bmkp-bmenu-edit-marked
+ :help "Edit internal records of marked bookmarks (which include their tags)"
+ :keys "T > e"))
+(define-key bmkp-bmenu-tags-menu [bmkp-bmenu-set-tag-value-for-marked]
+ '(menu-item "Set Tag Value for Marked..." bmkp-bmenu-set-tag-value-for-marked
+ :help "Set the value of a tag, for each of the marked bookmarks"))
+(define-key bmkp-bmenu-tags-menu [bmkp-remove-tags-from-all]
+ '(menu-item "Remove Some Tags from All..." bmkp-remove-tags-from-all
+ :help "Remove a set of tags from all bookmarks"))
+(define-key bmkp-bmenu-tags-menu [bmkp-bmenu-remove-tags-from-marked]
+ '(menu-item "Remove Some Tags from Marked..." bmkp-bmenu-remove-tags-from-marked
+ :help "Remove a set of tags from each of the marked bookmarks"))
+(define-key bmkp-bmenu-tags-menu [bmkp-bmenu-add-tags-to-marked]
+ '(menu-item "Add Some Tags to Marked..." bmkp-bmenu-add-tags-to-marked
+ :help "Add a set of tags to each of the marked bookmarks"))
+(define-key bmkp-bmenu-tags-menu [bmkp-bmenu-paste-replace-tags-for-marked]
+ '(menu-item "Paste Tags to Marked (Replace)..." bmkp-bmenu-paste-replace-tags-for-marked
+ :help "Replace tags for the marked bookmarks with set of tags copied previously"))
+(define-key bmkp-bmenu-tags-menu [bmkp-bmenu-paste-add-tags-to-marked]
+ '(menu-item "Paste Tags to Marked (Add)..." bmkp-bmenu-paste-add-tags-to-marked
+ :help "Add tags copied from another bookmark to the marked bookmarks"
+ :enable bmkp-copied-tags))
+(define-key bmkp-bmenu-tags-menu [bmkp-bmenu-copy-tags]
+ '(menu-item "Copy Tags from This Bookmark" bmkp-bmenu-copy-tags
+ :help "Copy tags from this bookmark, so you can paste them to other bookmarks"))
+
+
+;;; `Search' submenu -------------------------------------------------
+(define-key bmkp-bmenu-search-menu [bmkp-bmenu-query-replace-marked-bookmarks-regexp]
+ '(menu-item "Query-Replace Marked..." bmkp-bmenu-query-replace-marked-bookmarks-regexp
+ :help "`query-replace-regexp' over all files whose bookmarks are marked"))
+(when (fboundp 'bmkp-bmenu-isearch-marked-bookmarks)
+ (define-key bmkp-bmenu-search-menu [bmkp-bmenu-isearch-marked-bookmarks-regexp]
+ '(menu-item "Regexp-Isearch Marked..." bmkp-bmenu-isearch-marked-bookmarks-regexp
+ :help "Regexp Isearch the marked bookmark locations, in their current order"))
+ (define-key bmkp-bmenu-search-menu [bmkp-bmenu-isearch-marked-bookmarks]
+ '(menu-item "Isearch Marked..." bmkp-bmenu-isearch-marked-bookmarks
+ :help "Isearch the marked bookmark locations, in their current order")))
+(define-key bmkp-bmenu-search-menu [bmkp-bmenu-search-marked-bookmarks-regexp]
+ '(menu-item "Search Marked..." bmkp-bmenu-search-marked-bookmarks-regexp
+ :help "Regexp-search the files whose bookmarks are marked, in their current order"))
+
+
+;;; `Sort' submenu ---------------------------------------------------
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-url]
+ '(menu-item "By URL" bmkp-bmenu-sort-by-url
+ :help "Sort URL bookmarks alphabetically by their URL/filename"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-Gnus-thread]
+ '(menu-item "By Gnus Thread" bmkp-bmenu-sort-by-Gnus-thread
+ :help "Sort Gnus bookmarks by group, then by article, then by message"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-Info-node-name]
+ '(menu-item "By Info Node Name" bmkp-bmenu-sort-by-Info-node-name
+ :help "Sort Info bookmarks by manual (file) name, then node name, then position"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-Info-position]
+ '(menu-item "By Info Book Order" bmkp-bmenu-sort-by-Info-position
+ :help "Sort Info bookmarks by manual (file) name, then position (order in book)"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-last-local-file-update]
+ '(menu-item "By Last Local File Update" bmkp-bmenu-sort-by-last-local-file-update
+ :help "Sort bookmarks by last local file update time"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-last-buffer-or-file-access]
+ '(menu-item "By Last Buffer/File Access" bmkp-bmenu-sort-by-last-buffer-or-file-access
+ :help "Sort bookmarks by time of last buffer access or local-file access"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-local-file-size]
+ '(menu-item "By Local File Size" bmkp-bmenu-sort-by-local-file-size
+ :help "Sort bookmarks by local file size"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-local-file-type]
+ '(menu-item "By Local File Type" bmkp-bmenu-sort-by-local-file-type
+ :help "Sort bookmarks by local file type: file, symlink, directory"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-bookmark-type]
+ '(menu-item "By Type" bmkp-bmenu-sort-by-bookmark-type
+ :help "Sort bookmarks by type: Info, URL, Gnus, files, other"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-file-name]
+ '(menu-item "By File Name" bmkp-bmenu-sort-by-file-name :help "Sort bookmarks by file name"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-bookmark-name]
+ '(menu-item "By Bookmark Name" bmkp-bmenu-sort-by-bookmark-name
+ :help "Sort bookmarks by bookmark name, respecting `case-fold-search'"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-creation-time]
+ '(menu-item "By Creation Time" bmkp-bmenu-sort-by-creation-time
+ :help "Sort bookmarks by the time of their creation"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-last-bookmark-access]
+ '(menu-item "By Last Bookmark Access" bmkp-bmenu-sort-by-last-bookmark-access
+ :help "Sort bookmarks by the time of their last visit as bookmarks"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-by-bookmark-visit-frequency]
+ '(menu-item "By Bookmark Use" bmkp-bmenu-sort-by-bookmark-visit-frequency
+ :help "Sort bookmarks by the number of times they were visited as bookmarks"))
+(define-key bmkp-bmenu-sort-menu [bmkp-bmenu-sort-marked-before-unmarked]
+ '(menu-item "Marked Before Unmarked" bmkp-bmenu-sort-marked-before-unmarked
+ :help "Sort bookmarks by putting marked before unmarked"))
+(define-key bmkp-bmenu-sort-menu [bmkp-reverse-sort-order]
+ '(menu-item "Reverse" bmkp-reverse-sort-order :help "Reverse the current bookmark sort order"))
+
+;;; `Edit' submenu ---------------------------------------------------
+(define-key bmkp-bmenu-edit-menu [bmkp-bmenu-edit-marked]
+ '(menu-item "Edit Full Records of Marked (Lisp)" bmkp-bmenu-edit-marked
+ :help "Edit the full internal records of the marked bookmarks" :keys "E"))
+(define-key bmkp-bmenu-edit-menu [bmkp-bmenu-edit-bookmark-record]
+ '(menu-item "Edit Full Record (Lisp)" bmkp-bmenu-edit-bookmark-record
+ :help "Edit full record (Lisp sexp) for this bookmark, in another window"))
+(define-key bmkp-bmenu-edit-menu [bmkp-bmenu-edit-annotations-for-marked]
+ '(menu-item "Edit Annotations of Marked" bmkp-bmenu-edit-annotations-for-marked
+ :help "Edit annotations (created if missing) for the marked bookmarks"))
+(define-key bmkp-bmenu-edit-menu [bookmark-bmenu-edit-annotation]
+ '(menu-item "Edit Annotation" bookmark-bmenu-edit-annotation
+ :help "Edit annotation for this bookmark (create if none), in another window"))
+
+;;; `Show' submenu ---------------------------------------------------
+(define-key bmkp-bmenu-show-menu [bookmark-bmenu-show-all-annotations]
+ '(menu-item "Show All Annotations" bookmark-bmenu-show-all-annotations
+ :help "Show the annotations for all bookmarks (in another window)"))
+(define-key bmkp-bmenu-show-menu [bookmark-bmenu-show-annotation]
+ '(menu-item "Show Annotation" bookmark-bmenu-show-annotation
+ :help "Show the annotation for this bookmark (in another window)"
+ :enable (and (bookmark-bmenu-bookmark) (bookmark-get-annotation (bookmark-bmenu-bookmark)))))
+(define-key bmkp-bmenu-show-menu [bookmark-bmenu-toggle-filenames]
+ '(menu-item "Show/Hide File Names" bookmark-bmenu-toggle-filenames
+ :help "Toggle whether filenames are shown in the bookmark list"))
+
+(define-key bmkp-bmenu-show-menu [show-sep5] '("--")) ; --------------
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-filter-tags-incrementally]
+ '(menu-item "Show Only Tag Matches..." bmkp-bmenu-filter-tags-incrementally
+ :help "Incrementally filter bookmarks by tags using a regexp"))
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-filter-annotation-incrementally]
+ '(menu-item "Show Only Annotation Matches..." bmkp-bmenu-filter-annotation-incrementally
+ :help "Incrementally filter bookmarks by annotation using a regexp"))
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-filter-file-name-incrementally]
+ '(menu-item "Show Only File Name Matches..." bmkp-bmenu-filter-file-name-incrementally
+ :help "Incrementally filter bookmarks by file name using a regexp"))
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-filter-bookmark-name-incrementally]
+ '(menu-item "Show Only Name Matches..." bmkp-bmenu-filter-bookmark-name-incrementally
+ :help "Incrementally filter bookmarks by bookmark name using a regexp"))
+
+(define-key bmkp-bmenu-show-menu [show-sep3] '("--")) ; --------------
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-show-only-specific-file-bookmarks]
+ '(menu-item "Show Only for Specific File" bmkp-bmenu-show-only-specific-file-bookmarks
+ :help "Display (only) the bookmarks for a specific file"))
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-show-only-specific-buffer-bookmarks]
+ '(menu-item "Show Only for Specific Buffer" bmkp-bmenu-show-only-specific-buffer-bookmarks
+ :help "Display (only) the bookmarks for a specific buffer"))
+
+(define-key bmkp-bmenu-show-menu [show-sep2] '("--")) ; --------------
+(when (featurep 'bookmark+-lit)
+ (define-key bmkp-bmenu-show-menu [bmkp-bmenu-show-only-lighted-bookmarks]
+ '(menu-item "Show Only Highlighted" bmkp-bmenu-show-only-lighted-bookmarks
+ :help "Display (only) highlighted bookmarks")))
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-show-only-temporary-bookmarks]
+ '(menu-item "Show Only Temporaries" bmkp-bmenu-show-only-temporary-bookmarks
+ :help "Display (only) the temporary bookmarks (`X')"))
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-show-only-autonamed-bookmarks]
+ '(menu-item "Show Only Autonamed" bmkp-bmenu-show-only-autonamed-bookmarks
+ :help "Display (only) the autonamed bookmarks"))
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-show-only-autofile-bookmarks]
+ '(menu-item "Show Only Autofiles" bmkp-bmenu-show-only-autofile-bookmarks
+ :help "Display (only) the autofile bookmarks: those named the same as their files"))
+
+(define-key bmkp-bmenu-show-menu [show-sep1] '("--")) ; --------------
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-toggle-show-only-unmarked]
+ '(menu-item "Show Only Unmarked" bmkp-bmenu-toggle-show-only-unmarked
+ :help "Hide all marked bookmarks. Repeat to toggle, showing all"))
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-toggle-show-only-marked]
+ '(menu-item "Show Only Marked" bmkp-bmenu-toggle-show-only-marked
+ :help "Hide all unmarked bookmarks. Repeat to toggle, showing all"))
+(define-key bmkp-bmenu-show-menu [bmkp-bmenu-show-all]
+ '(menu-item "Show All" bmkp-bmenu-show-all
+ :help "Show all bookmarks currently known to the bookmark list"))
+
+
+;;; `Show' > `Only Bookmarks of Type' submenu -----------------------------
+
+(defvar bmkp-bmenu-show-types-menu (make-sparse-keymap "Only Bookmarks of Type")
+ "`Only Bookmarks of Type' submenu for `Show' submenu of `Bookmark+' menu.")
+(define-key bmkp-bmenu-show-menu [type] (cons "Only Bookmarks of Type" bmkp-bmenu-show-types-menu))
+
+(define-key bmkp-bmenu-show-types-menu [show-sep4] '("--")) ; --------------
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-w3m-bookmarks]
+ '(menu-item "W3M URLs" bmkp-bmenu-show-only-w3m-bookmarks
+ :help "Display (only) the W3M URL bookmarks"))
+(when (fboundp 'bmkp-bmenu-show-only-eww-bookmarks) ; Emacs 25+
+ (define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-eww-bookmarks]
+ '(menu-item "EWW URLs" bmkp-bmenu-show-only-eww-bookmarks
+ :help "Display (only) the EWW URL bookmarks")))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-url-bookmarks]
+ '(menu-item "URLs" bmkp-bmenu-show-only-url-bookmarks
+ :help "Display (only) the URL bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-man-bookmarks]
+ '(menu-item "UNIX Manual Pages" bmkp-bmenu-show-only-man-bookmarks
+ :help "Display (only) the `man' page bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-untagged-bookmarks]
+ '(menu-item "Untagged" bmkp-bmenu-show-only-untagged-bookmarks
+ :help "Display (only) the bookmarks that do not have tags"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-tagged-bookmarks]
+ '(menu-item "Tagged" bmkp-bmenu-show-only-tagged-bookmarks
+ :help "Display (only) the bookmarks that have tags"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-variable-list-bookmarks]
+ '(menu-item "Variable Lists" bmkp-bmenu-show-only-variable-list-bookmarks
+ :help "Display (only) the variable-list bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-function-bookmarks]
+ '(menu-item "Functions" bmkp-bmenu-show-only-function-bookmarks
+ :help "Display (only) the function bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-snippet-bookmarks]
+ '(menu-item "Snippets" bmkp-bmenu-show-only-snippet-bookmarks
+ :help "Display (only) the snippet bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-region-bookmarks]
+ '(menu-item "Regions" bmkp-bmenu-show-only-region-bookmarks
+ :help "Display (only) the bookmarks that record a region"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-orphaned-local-file-bookmarks]
+ '(menu-item "Orphaned Local Files" bmkp-bmenu-show-only-orphaned-local-file-bookmarks
+ :help "Display (only) orphaned local-file bookmarks (`C-u': show remote also)"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-non-invokable-bookmarks]
+ '(menu-item "Non-Invokable" bmkp-bmenu-show-only-non-invokable-bookmarks
+ :help "Display (only) the non-invokable bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-non-file-bookmarks]
+ '(menu-item "Non-Files (Buffers)" bmkp-bmenu-show-only-non-file-bookmarks
+ :help "Display (only) the non-file bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-image-bookmarks]
+ '(menu-item "Image Files" bmkp-bmenu-show-only-image-bookmarks
+ :help "Display (only) image-file bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-icicles-search-hits-bookmarks]
+ '(menu-item "Icicles Search-Hits" bmkp-bmenu-show-only-icicles-search-hits-bookmarks
+ :help "Display (only) Icicles search-hits bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-info-bookmarks]
+ '(menu-item "Info Nodes" bmkp-bmenu-show-only-info-bookmarks
+ :help "Display (only) the Info bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-gnus-bookmarks]
+ '(menu-item "Gnus Messages" bmkp-bmenu-show-only-gnus-bookmarks
+ :help "Display (only) the Gnus bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-file-bookmarks]
+ '(menu-item "Files" bmkp-bmenu-show-only-file-bookmarks
+ :help "Display (only) the file and directory bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-dired-bookmarks]
+ '(menu-item "Dired Buffers" bmkp-bmenu-show-only-dired-bookmarks
+ :help "Display (only) the Dired bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-desktop-bookmarks]
+ '(menu-item "Desktops" bmkp-bmenu-show-only-desktop-bookmarks
+ :help "Display (only) the desktop bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-bookmark-list-bookmarks]
+ '(menu-item "Bookmark Lists" bmkp-bmenu-show-only-bookmark-list-bookmarks
+ :help "Display (only) the bookmark-list bookmarks"))
+(define-key bmkp-bmenu-show-types-menu [bmkp-bmenu-show-only-bookmark-file-bookmarks]
+ '(menu-item "Bookmark Files" bmkp-bmenu-show-only-bookmark-file-bookmarks
+ :help "Display (only) the bookmark-file bookmarks"))
+
+
+;;; `Omit' submenu ---------------------------------------------------
+(define-key bmkp-bmenu-omit-menu [bmkp-bmenu-show-all]
+ '(menu-item "Show All" bmkp-bmenu-show-all
+ :visible (eq bmkp-bmenu-filter-function 'bmkp-omitted-alist-only)
+ :help "Show all bookmarks (except omitted)"))
+(define-key bmkp-bmenu-omit-menu [bmkp-bmenu-show-only-omitted-bookmarks]
+ '(menu-item "Show Only Omitted" bmkp-bmenu-show-only-omitted-bookmarks
+ :visible (not (eq bmkp-bmenu-filter-function 'bmkp-omitted-alist-only))
+ :enable bmkp-bmenu-omitted-bookmarks :help "Show only the omitted bookmarks"))
+(define-key bmkp-bmenu-omit-menu [bmkp-unomit-all]
+ '(menu-item "Un-Omit All" bmkp-unomit-all
+ :visible bmkp-bmenu-omitted-bookmarks :help "Un-omit all omitted bookmarks"))
+(define-key bmkp-bmenu-omit-menu [bmkp-bmenu-unomit-marked]
+ '(menu-item "Un-Omit Marked" bmkp-bmenu-unomit-marked
+ :visible (eq bmkp-bmenu-filter-function 'bmkp-omitted-alist-only)
+ :enable (and bmkp-bmenu-omitted-bookmarks
+ (save-excursion (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (re-search-forward "^>" (point-max) t)))
+ :help "Un-omit the marked bookmarks" :keys "\\[bmkp-bmenu-omit/unomit-marked]"))
+(define-key bmkp-bmenu-omit-menu [bmkp-bmenu-omit-marked]
+ '(menu-item "Omit Marked" bmkp-bmenu-omit-marked
+ :visible (not (eq bmkp-bmenu-filter-function 'bmkp-omitted-alist-only))
+ :enable (save-excursion (goto-char (point-min)) (forward-line bmkp-bmenu-header-lines)
+ (re-search-forward "^>" (point-max) t))
+ :help "Omit the marked bookmarks" :keys "\\[bmkp-bmenu-omit/unomit-marked]"))
+
+
+;;; `Mark' submenu ---------------------------------------------------
+(define-key bmkp-bmenu-mark-menu [mark-sep5] '("--")) ; --------------
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-load-marking-unmark-first]
+ '(menu-item "Load Bookmark File, Mark Only Loaded...." bmkp-bmenu-load-marking-unmark-first
+ :help "`bookmark-load', marking only bookmarks that are loaded."))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-load-marking]
+ '(menu-item "Load Bookmark File, Mark Loaded...." bmkp-bmenu-load-marking
+ :help "`bookmark-load', but mark bookmarks that are loaded. C-u: unmark all first."))
+
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-unmark-bookmarks-tagged-not-all]
+ '(menu-item "Unmark If Not Tagged with All..." bmkp-bmenu-unmark-bookmarks-tagged-not-all
+ :help "Unmark all visible bookmarks that are tagged with *some* tag in a set you specify"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-unmark-bookmarks-tagged-none]
+ '(menu-item "Unmark If Tagged with None..." bmkp-bmenu-unmark-bookmarks-tagged-none
+ :help "Unmark all visible bookmarks that are *not* tagged with *any* tag you specify"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-unmark-bookmarks-tagged-all]
+ '(menu-item "Unmark If Tagged with All..." bmkp-bmenu-unmark-bookmarks-tagged-all
+ :help "Unmark all visible bookmarks that are tagged with *each* tag you specify"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-unmark-bookmarks-tagged-some]
+ '(menu-item "Unmark If Tagged with Some..." bmkp-bmenu-unmark-bookmarks-tagged-some
+ :help "Unmark all visible bookmarks that are tagged with *some* tag in a set you specify"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-unmark-bookmarks-tagged-regexp]
+ '(menu-item "Unmark If Tagged Matching Regexp..." bmkp-bmenu-unmark-bookmarks-tagged-regexp
+ :help "Unmark bookmarks any of whose tags match a regexp you enter"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-bookmarks-tagged-not-all]
+ '(menu-item "Mark If Not Tagged with All..." bmkp-bmenu-mark-bookmarks-tagged-not-all
+ :help "Mark all visible bookmarks that are *not* tagged with *all* tags you specify"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-bookmarks-tagged-none]
+ '(menu-item "Mark If Tagged with None..." bmkp-bmenu-mark-bookmarks-tagged-none
+ :help "Mark all visible bookmarks that are not tagged with *any* tag you specify"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-bookmarks-tagged-all]
+ '(menu-item "Mark If Tagged with All..." bmkp-bmenu-mark-bookmarks-tagged-all
+ :help "Mark all visible bookmarks that are tagged with *each* tag you specify"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-bookmarks-tagged-some]
+ '(menu-item "Mark If Tagged with Some..." bmkp-bmenu-mark-bookmarks-tagged-some
+ :help "Mark all visible bookmarks that are tagged with *some* tag in a set you specify"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-bookmarks-tagged-regexp]
+ '(menu-item "Mark If Tagged Matching Regexp..." bmkp-bmenu-mark-bookmarks-tagged-regexp
+ :help "Mark bookmarks any of whose tags match a regexp you enter"))
+
+(define-key bmkp-bmenu-mark-menu [mark-sep3] '("--")) ; --------------
+(when (featurep 'bookmark+-lit)
+ (define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-lighted-bookmarks]
+ '(menu-item "Mark Highlighted" bmkp-bmenu-mark-lighted-bookmarks
+ :help "Mark highlighted bookmarks")))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-temporary-bookmarks]
+ '(menu-item "Mark Temporaries" bmkp-bmenu-mark-temporary-bookmarks
+ :help "Mark temporary bookmarks (those with `X')"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-autonamed-bookmarks]
+ '(menu-item "Mark Autonamed" bmkp-bmenu-mark-autonamed-bookmarks
+ :help "Mark autonamed bookmarks"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-autofile-bookmarks]
+ '(menu-item "Mark Autofiles" bmkp-bmenu-mark-autofile-bookmarks
+ :help "Mark autofile bookmarks: those whose names are the same as their files"))
+
+(define-key bmkp-bmenu-mark-menu [mark-sep2] '("--")) ; --------------
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-unmark-all]
+ '(menu-item "Unmark All" bmkp-bmenu-unmark-all
+ :help "Remove a mark you specify (> or D) from each bookmark (RET to remove both kinds)"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-all]
+ '(menu-item "Mark All" bmkp-bmenu-mark-all :help "Mark all bookmarks, using mark `>'"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-toggle-marks]
+ '(menu-item "Toggle Marked/Unmarked" bmkp-bmenu-toggle-marks
+ :help "Unmark all marked bookmarks; mark all unmarked bookmarks"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-regexp-mark]
+ '(menu-item "Mark Regexp Matches..." bmkp-bmenu-regexp-mark
+ :help "Mark bookmarks that match a regexp that you enter"))
+
+(define-key bmkp-bmenu-mark-menu [mark-sep4] '("--")) ; --------------
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-specific-file-bookmarks]
+ '(menu-item "Mark for Specific File" bmkp-bmenu-mark-specific-file-bookmarks
+ :help "Mark bookmarks for a specific file"))
+(define-key bmkp-bmenu-mark-menu [bmkp-bmenu-mark-specific-buffer-bookmarks]
+ '(menu-item "Mark for Specific Buffer" bmkp-bmenu-mark-specific-buffer-bookmarks
+ :help "Mark bookmarks for a specific buffer"))
+
+
+;; `Mark' > `Bookmarks of Type' submenu ------------------------------
+(defvar bmkp-bmenu-mark-types-menu (make-sparse-keymap "Bookmarks of Type")
+ "`Bookmarks of Type' submenu for `Mark' submenu of m`Bookmark+' menu.")
+(define-key bmkp-bmenu-mark-menu [type] (cons "Bookmarks of Type" bmkp-bmenu-mark-types-menu))
+
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-w3m-bookmarks]
+ '(menu-item "W3M URLs" bmkp-bmenu-mark-w3m-bookmarks :help "Mark W3M URL bookmarks"))
+(when (fboundp 'bmkp-bmenu-mark-eww-bookmarks) ; Emacs 25+
+ (define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-eww-bookmarks]
+ '(menu-item "EWW URLs" bmkp-bmenu-mark-eww-bookmarks :help "Mark Eww URL bookmarks")))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-url-bookmarks]
+ '(menu-item "URLs" bmkp-bmenu-mark-url-bookmarks :help "Mark URL bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-variable-list-bookmarks]
+ '(menu-item "Variable Lists" bmkp-bmenu-mark-variable-list-bookmarks
+ :help "Mark the variable-list bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-man-bookmarks]
+ '(menu-item "UNIX Manual Pages" bmkp-bmenu-mark-man-bookmarks
+ :help "Mark `man' page bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-snippet-bookmarks]
+ '(menu-item "Snippets" bmkp-bmenu-mark-snippet-bookmarks
+ :help "Mark snippet bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-region-bookmarks]
+ '(menu-item "Regions" bmkp-bmenu-mark-region-bookmarks
+ :help "Mark bookmarks that record a region"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-orphaned-local-file-bookmarks]
+ '(menu-item "Orphaned Local Files" bmkp-bmenu-mark-orphaned-local-file-bookmarks
+ :help "Mark orphaned local-file bookmarks (`C-u': remote also)"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-non-invokable-bookmarks]
+ '(menu-item "Non-Invokable" bmkp-bmenu-mark-non-invokable-bookmarks
+ :help "Mark non-invokable bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-non-file-bookmarks]
+ '(menu-item "Non-Files (Buffers)" bmkp-bmenu-mark-non-file-bookmarks
+ :help "Mark non-file bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-image-bookmarks]
+ '(menu-item "Images" bmkp-bmenu-mark-image-bookmarks :help "Mark image-file bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-icicles-search-hits-bookmarks]
+ '(menu-item "Icicle Search Hits" bmkp-bmenu-mark-icicles-search-hits-bookmarks
+ :help "Mark Icicles search-hit bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-info-bookmarks]
+ '(menu-item "Info Nodes" bmkp-bmenu-mark-info-bookmarks :help "Mark Info bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-gnus-bookmarks]
+ '(menu-item "Gnus Messages" bmkp-bmenu-mark-gnus-bookmarks :help "Mark Gnus bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-file-bookmarks]
+ '(menu-item "Files" bmkp-bmenu-mark-file-bookmarks :help "Mark file bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-dired-bookmarks]
+ '(menu-item "Dired Buffers" bmkp-bmenu-mark-dired-bookmarks :help "Mark Dired bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-desktop-bookmarks]
+ '(menu-item "Desktops" bmkp-bmenu-mark-desktop-bookmarks
+ :help "Mark desktop bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-bookmark-list-bookmarks]
+ '(menu-item "Bookmark Lists" bmkp-bmenu-mark-bookmark-list-bookmarks
+ :help "Mark the bookmark-list bookmarks"))
+(define-key bmkp-bmenu-mark-types-menu [bmkp-bmenu-mark-bookmark-file-bookmarks]
+ '(menu-item "Bookmark Files" bmkp-bmenu-mark-bookmark-file-bookmarks
+ :help "Mark the bookmark-file bookmarks"))
+
+
+;;; `Delete' submenu -------------------------------------------------
+(define-key bmkp-bmenu-delete-menu [bookmark-bmenu-execute-deletions]
+ '(menu-item "Delete Flagged (D)..." bookmark-bmenu-execute-deletions
+ :help "Delete the (visible) bookmarks flagged `D'"))
+(define-key bmkp-bmenu-delete-menu [bmkp-bmenu-delete-marked]
+ '(menu-item "Delete Marked (>)..." bmkp-bmenu-delete-marked
+ :help "Delete all (visible) bookmarks marked `>', after confirmation"))
+(define-key bmkp-bmenu-delete-menu [bmkp-delete-all-temporary-bookmarks]
+ '(menu-item "Delete All Temporaries..." bmkp-delete-all-temporary-bookmarks
+ :help "Delete the temporary bookmarks, (`X') whether visible here or not"))
+
+
+;;; `Edit' menu-bar menu
+
+;; `menu-bar+.el' redefines `menu-bar-edit-menu'.
+;; Soft-require it in `condition-case' because it soft-requires Bookmark+.
+(condition-case nil (require 'menu-bar+ nil t) (error nil))
+
+(define-key-after menu-bar-edit-menu [separator-snippet] '("--") 'mark-whole-buffer)
+(define-key-after menu-bar-edit-menu [bmkp-set-snippet-bookmark]
+ '(menu-item "Region to Snippet..." bmkp-set-snippet-bookmark
+ :help "Save the region text to a snippet bookmark"
+ :enable (and mark-active (not buffer-read-only))) 'separator-snippet)
+(define-key-after menu-bar-edit-menu [bmkp-snippet-to-kill-ring]
+ '(menu-item "Snippet to Kill Ring..." bmkp-snippet-to-kill-ring
+ :help "Copy the text saved in a snippet bookmark to the `kill-ring'")
+ 'bmkp-set-snippet-bookmark)
+
+
+
+;;;---------------------------------------------------------------------------------------
+
+;;; Mouse-3 menu binding.
+
+(defvar bmkp-bmenu-line-overlay nil
+ "Overlay to highlight the current line for `bmkp-bmenu-mouse-3-menu'.")
+(define-key bookmark-bmenu-mode-map [down-mouse-3] 'bmkp-bmenu-mouse-3-menu)
+(define-key bookmark-bmenu-mode-map [mouse-3] 'ignore)
+
+;;;###autoload (autoload 'bmkp-bmenu-mouse-3-menu "bookmark+")
+(defun bmkp-bmenu-mouse-3-menu (event)
+ "Pop-up menu on `mouse-3' for a bookmark listed in `*Bookmark List*'."
+ (interactive "e")
+ (let* ((mouse-pos (event-start event))
+ (inhibit-field-text-motion t) ; Just in case.
+ bol eol bmk-name)
+ (with-current-buffer (window-buffer (posn-window mouse-pos))
+ (save-excursion
+ (goto-char (posn-point mouse-pos))
+ (setq bol (line-beginning-position)
+ eol (line-end-position))
+ (unwind-protect
+ (progn
+ (if bmkp-bmenu-line-overlay ; Don't re-create.
+ (move-overlay bmkp-bmenu-line-overlay bol eol (current-buffer))
+ (setq bmkp-bmenu-line-overlay (make-overlay bol eol))
+ (overlay-put bmkp-bmenu-line-overlay 'face 'region))
+ (setq bmk-name (bookmark-bmenu-bookmark))
+ (when bmk-name
+ (sit-for 0)
+ (let* ((map (easy-menu-create-menu
+ "This Bookmark"
+ `(,(if (bmkp-bookmark-name-member bmk-name bmkp-bmenu-marked-bookmarks)
+ ["Unmark" bookmark-bmenu-unmark]
+ ["Mark" bookmark-bmenu-mark])
+ ,(save-excursion
+ (goto-char (posn-point mouse-pos))
+ (beginning-of-line)
+ (if (bmkp-looking-at-p "^D")
+ ["Unmark" bookmark-bmenu-unmark]
+ ["Flag for Deletion" bmkp-bmenu-flag-for-deletion]))
+ ["Omit" bmkp-bmenu-omit]
+ ["Jump To" bookmark-bmenu-this-window]
+ ["Jump To in Other Window" bookmark-bmenu-other-window]
+
+ "--" ; ----------------------------------------------------
+ ["Edit Tags..." bmkp-bmenu-edit-tags
+ :active (bmkp-get-tags bmk-name)]
+ ["Copy Tags" bmkp-bmenu-copy-tags
+ ;; You can copy an empty list of tags and paste-replace with it.
+ ;; :active (bmkp-get-tags bmk-name)
+ ]
+ ["Paste Tags (Add)" bmkp-bmenu-paste-add-tags
+ :active bmkp-copied-tags]
+ ["Paste Tags (Replace)" bmkp-bmenu-paste-replace-tags
+ ;; You can paste an empty list of tags to replace tags.
+ ;; :active bmkp-copied-tags
+ ]
+ ["Add Some Tags..." bmkp-bmenu-add-tags]
+ ["Remove Some Tags..." bmkp-bmenu-remove-tags
+ :active (bmkp-get-tags bmk-name)]
+ ["Remove All Tags..." bmkp-bmenu-remove-all-tags
+ :active (bmkp-get-tags bmk-name)]
+ ["Set Tag Value..." bmkp-bmenu-set-tag-value
+ :active (bmkp-get-tags bmk-name)]
+ ["Rename Tag..." bmkp-rename-tag
+ :active (bmkp-get-tags bmk-name)]
+
+ ["--" 'ignore :visible (featurep 'bookmark+-lit)] ; ---------------
+ ["Highlight" bmkp-bmenu-light
+ :visible (featurep 'bookmark+-lit)
+ :active (not (bmkp-lighted-p bmk-name))]
+ ["Unhighlight" bmkp-bmenu-unlight
+ :visible (featurep 'bookmark+-lit)
+ :active (bmkp-lighted-p bmk-name)]
+ ["Set Lighting" bmkp-bmenu-set-lighting
+ :visible (featurep 'bookmark+-lit)]
+
+ "--" ; ----------------------------------------------------
+ ["Toggle Temporary/Savable" bmkp-bmenu-toggle-temporary]
+ ,@(and (fboundp 'org-add-link-type)
+ '(["Store Org Link" org-store-link]))
+ ["Rename or Relocate..." bmkp-bmenu-edit-bookmark-name-and-location]
+ ["Clone (Duplicate)" bmkp-bmenu-clone-bookmark]
+ ["Edit Internal Record (Lisp)..." bmkp-bmenu-edit-bookmark-record]
+ ["Show Annotation" bookmark-bmenu-show-annotation
+ :active (bookmark-get-annotation bmk-name)]
+ ["Edit Annotation..." bookmark-bmenu-edit-annotation]
+
+ "--" ; ----------------------------------------------------
+ ["Describe" bmkp-bmenu-describe-this-bookmark])))
+ (choice (x-popup-menu event map)))
+ (when choice
+ (call-interactively (lookup-key map (apply 'vector choice)))))))
+ (when bmkp-bmenu-line-overlay (delete-overlay bmkp-bmenu-line-overlay)))))))
+
+;;;;;;;;;;;;;;;;;;;;;
+
+(provide 'bookmark+-bmu)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; bookmark+-bmu.el ends here
--- /dev/null
+;;; bookmark+-chg.el - Change logs for Bookmark+ libraries.
+;;
+;; Filename: bookmark+-chg.el
+;; Description: Change logs for Bookmark+ libraries.
+;; Author: Drew Adams
+;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com")
+;; Copyright (C) 2000-2022, Drew Adams, all rights reserved.
+;; Created: Fri Sep 15 07:58:41 2000
+;; Last-Updated: Fri Jan 14 12:54:17 2022 (-0800)
+;; By: dradams
+;; Update #: 16855
+;; URL: https://www.emacswiki.org/emacs/download/bookmark%2b-chg.el
+;; Doc URL: https://www.emacswiki.org/emacs/BookmarkPlus
+;; Keywords: bookmarks, bookmark+
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x, 26.
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Change log for the Bookmark+ libraries, which extend standard
+;; library `bookmark.el'. This file contains no code, so you need
+;; not load it.
+;;
+;; The Bookmark+ libraries are these:
+;;
+;; `bookmark+.el' - main (driver) code library
+;; `bookmark+-mac.el' - Lisp macros
+;; `bookmark+-lit' - (optional) code for highlighting bookmarks
+;; `bookmark+-bmu.el' - code for the `*Bookmark List*' (bmenu)
+;; `bookmark+-1.el' - other (non-bmenu) required code
+;; `bookmark+-key.el' - key and menu bindings
+;;
+;; `bookmark+-doc' - documentation (comment-only file)
+;; `bookmark+-chg' - change log (this file)
+;;
+;; The documentation (in `bookmark+-doc.el') includes how to
+;; byte-compile and install Bookmark+. The documentation is also
+;; available in these ways:
+;;
+;; 1. From the bookmark list (`C-x r l'):
+;; Use `?' to show the current bookmark-list status and general
+;; help, then click link `Doc in Commentary' or link `Doc on the
+;; Web'.
+;;
+;; 2. From the Emacs-Wiki Web site:
+;; https://www.emacswiki.org/emacs/BookmarkPlus.
+;;
+;; 3. From the Bookmark+ group customization buffer:
+;; `M-x customize-group bookmark-plus', then click link
+;; `Commentary'.
+;;
+;; (The commentary links in #1 and #3 work only if you put library
+;; `bookmark+-doc.el' in your `load-path'.)
+;;
+;;
+;; ****** NOTE ******
+;;
+;; WHENEVER you update Bookmark+ (i.e., download new versions of
+;; Bookmark+ source files), I recommend that you do the
+;; following:
+;;
+;; 1. Delete ALL existing BYTE-COMPILED Bookmark+ files
+;; (bookmark+*.elc).
+;; 2. Load Bookmark+ (`load-library' or `require').
+;; 3. Byte-compile the source files.
+;;
+;; In particular, ALWAYS LOAD `bookmark+-mac.el' (not
+;; `bookmark+-mac.elc') BEFORE YOU BYTE-COMPILE new versions of
+;; the files, in case there have been any changes to Lisp macros
+;; (in `bookmark+-mac.el').
+;;
+;; (This is standard procedure for Lisp: code that depends on
+;; macros needs to be byte-compiled anew after loading the
+;; updated macros.)
+;;
+;; ******************
+;;
+;;
+;; ****** NOTE ******
+;;
+;; On 2010-06-18, I changed the prefix used by package Bookmark+
+;; from `bookmarkp-' to `bmkp-'. THIS IS AN INCOMPATIBLE CHANGE.
+;; I apologize for the inconvenience, but the new prefix is
+;; preferable for a number of reasons, including easier
+;; distinction from standard `bookmark.el' names.
+;;
+;; This change means that YOU MUST MANUALLY REPLACE ALL
+;; OCCURRENCES of `bookmarkp-' by `bmkp-' in the following
+;; places, if you used Bookmark+ prior to this change:
+;;
+;; 1. In your init file (`~/.emacs') or your `custom-file', if
+;; you have one. This is needed if you customized any
+;; Bookmark+ features.
+;;
+;; 2. In your default bookmark file, `bookmark-default-file'
+;; (`.emacs.bmk'), and in any other bookmark files you might
+;; have.
+;;
+;; 3. In your `*Bookmark List*' state file,
+;; `bmkp-bmenu-state-file' (`~/.emacs-bmk-bmenu-state.el').
+;;
+;; 4. In your `*Bookmark List*' commands file,
+;; `bmkp-bmenu-commands-file' (`~/.emacs-bmk-bmenu-commands.el'),
+;; if you have one.
+;;
+;; You can do this editing in a virgin Emacs session (`emacs
+;; -Q'), that is, without loading Bookmark+.
+;;
+;; Alternatively, you can do this editing in an Emacs session
+;; where Bookmark+ has been loaded, but in that case you must
+;; TURN OFF AUTOMATIC SAVING of both your default bookmark file
+;; and your `*Bookmark List*' state file. Otherwise, when you
+;; quit Emacs your manually edits will be overwritten.
+;;
+;; To turn off this automatic saving, you can use `M-~' and `M-l'
+;; in buffer `*Bookmark List*' (commands
+;; `bmkp-toggle-saving-bookmark-file' and
+;; `bmkp-toggle-saving-menu-list-state' - they are also in the
+;; `Bookmark+' menu).
+;;
+;;
+;; Again, sorry for this inconvenience.
+;;
+;; ******************
+
+;;(@> "Index")
+;;
+;; If you have library `linkd.el' and Emacs 22 or later, load
+;; `linkd.el' and turn on `linkd-mode' now. It lets you easily
+;; navigate around the sections of this doc. Linkd mode will
+;; highlight this Index, as well as the cross-references and section
+;; headings throughout this file. You can get `linkd.el' here:
+;; https://www.emacswiki.org/emacs/download/linkd.el.
+;;
+;; (@> "CHANGE LOG FOR `bookmark+-1.el'")
+;; (@> "CHANGE LOG FOR `bookmark+-bmu.el'")
+;; (@> "CHANGE LOG FOR `bookmark+-doc.el'")
+;; (@> "CHANGE LOG FOR `bookmark+-key.el'")
+;; (@> "CHANGE LOG FOR `bookmark+-lit.el'")
+;; (@> "CHANGE LOG FOR `bookmark+-mac.el'")
+;; (@> "CHANGE LOG FOR `bookmark+.el'")
+
+;;;(@* "CHANGE LOG FOR `bookmark+-1.el'")
+;;
+;; 2021/09/19 dadams
+;; Everywhere: Use bmkp-bmenu-buffer, not vanilla bookmark-bmenu-buffer.
+;; bmkp-bmenu-barf-if-not-in-menu-list: Test mode with derived-mode-p; don't test buffer name.
+;; 2020/08/21 dadams
+;; bookmark-set: Moved making bmk temporary before bookmark-store, and pass RECORD, not BNAME.
+;; bmkp(*)-automatic*: Put defvaralias symbols in right order.
+;; 2021/08/18 dadams
+;; Added: bmkp-set-automatic-bookmark.
+;; Renamed: bmkp(*)-auto-idle* to bmkp(*)-automatic*. Added defvaralias for old names.
+;; 2021/04/18 dadams
+;; Added back a redefinition of bookmark-get-bookmark, as bmkp-get-bookmark with NO-NAME-CHECK-P.
+;; bookmark-set-name, bookmark-location:
+;; Replaced (bmkp-get-bookmark BMK nil 'NO-NAME-CHECK-P) with (bookmark-get-bookmark BMK).
+;; Doc string and comment improvements, vis a vis uses of bookmark|bmkp-get-bookmark.
+;; 2021/04/16 dadams
+;; bookmark-get-bookmark-record, bookmark-set-name, bookmark-prop-set, bookmark-location,
+;; bookmark-delete, bookmark-show-annotation:
+;; Use bmkp-get-bookmark, not bookmark-get-bookmark, but in vanilla-compatible way.
+;; 2021/04/13 dadams
+;; Added: bmkp-get-bookmark. Removed redefinition of vanilla bookmark-get-bookmark.
+;; Problem was that some 3rd-party code uses bookmark-prop-set with unfinished bookmark record
+;; that has no name. Thx to Daniel Fleischer.
+;; bookmark-prop-set: Added optional arg REQUIRE-NAME-P. Pass it to bmkp-get-bookmark.
+;; bookmark-handle-bookmark, bookmark-default-handler, bmkp-jump-1,
+;; bmkp-show-this-annotation-read-only, bmkp-edit-this-annotation, bmkp-clone-bookmark,
+;; bmkp-update-autonamed-bookmark, bmkp-*-bookmark-p, bmkp-*-(c)p, bmkp-insert-bookmark-link,
+;; bmkp-describe-bookmark(-internals), bmkp-bookmark-description, bmkp-handle-region-default,
+;; bmkp-set-sequence-bookmark, bmkp-set-eww-bookmark-here, bmkp-jump-man,
+;; bmkp-cycle(-1|-this-(file|buffer)):
+;; Use bmkp-get-bookmark, not bookmark-get-bookmark.
+;; 2021/03/17 dadams
+;; Use buffer-string, not buffer-substring, for whole buffer.
+;; 2021/03/09 dadams
+;; bmkp-handle-region-default: Set region and activate it at the end.
+;; 2021/03/05 dadams
+;; Added: bmkp-read-buffers, bmkp-read-files.
+;; bmkp(autofile|file(-this-dir))-(all|some)-tags(-regexp)-alist-only,
+;; bmkp-specific-(buffers|files)-alist-only: Put property bmkp-read-arg with read-fn value.
+;; bmkp-read-regexp: Made PROMPT arg optional.
+;; bmkp-specific-(buffers|files)-jump(-other-window): Use bmkp-read-(buffers|files).
+;; bmkp-set-autonamed-regexp-(buffer|region): Removed prompt from call to bmkp-read-regexp.
+;; bmkp-annotate-bookmark-this-file/buffer, bmkp-edit-bookmark-record-file/buffer:
+;; Fixed format spec.
+;; 2021/03/04 dadams
+;; Added bmkp-types-alist. The def is also in bookmark+-mac.el.
+;; 2020/11/28 dadams
+;; Removed:
+;; bmkp-bookmark-type-valid-p, variable (defconst) bmkp-types-alist, and all history variables.
+;; Replaced all occurrences of variable bmkp-types-alist with function bmkp-types-alist.
+;; Invoke macro bmkp-define-history-variables to define history vars, after defining filter fns.
+;; Moved filter-function definitions to beginning of Bookmark+ functions section.
+;; bmkp-edit-tags-send: Don't use bmkp-bookmark-type-valid-p - needs to work with unknown types.
+;; 2020/11/23 dadams
+;; bmkp-url-target-set: Use read-from-minibuffer, not read-file-name, as fallback if no ffap.
+;; TEMPORARILY work around Emacs bug #44822 with phony default URL.
+;; 2020/08/30 dadams
+;; Added: Info-bookmark-use-only-node-not-file-flag, redefinition of Info-bookmark-jump.
+;; 2020/07/04 dadams
+;; Same commands as 7/03: Remove bmkp-propertize-*-flag as part of test for getting full bmk.
+;; Changed all references to `C-x p' to `C-x x'.
+;; Replaced string *Bookmark List* with bookmark-bmenu-buffer (for Emacs 28).
+;; bookmark-(edit|show)-annotation, bmkp-annotate-bookmark,
+;; bmkp-(edit|show)-this-annotation(-read-only):
+;; Replaced set make-local-variable bookmark-annotation-name by setq (auto-local in Emacs 28).
+;; 2020/07/03 dadams
+;; bmkp-read-bookmark-for-type:
+;; Use bmkp-bookmark-record-from-name to return full bookmark from ALIST.
+;; bmkp-(choose-navlist-from-bookmark-list|bookmark-file(-load|-switch)-jump|
+;; snippet-to-kill-ring|desktop-delete|
+;; (autonamed(-*)|dired(-*)|eww|(local|remote(-*)-|non-dir-)file(-*)|gnus|image|info|man|
+;; non-file|specific-(buffers|files)|temporary|this-buffer|url|w3m|autofile)-jump*|
+;; (bookmark-list|desktop|variable-list|w32-browser)-jump):
+;; Use bmkp-get-bookmark-in-alist to get full bmk.
+;; bmkp-jump-to-type*: Raise error if bookmark name, not record.
+;; 2020/07/02 dadams
+;; bmkp-specific-files-alist-only: Don't use member, use bmkp-same-file-p as equality test.
+;; 2020/06/20 dadams
+;; Added: bmkp-set-grep-command-bookmark.
+;; 2020/01/31 dadams
+;; bmkp-dired-remember-*-marks:
+;; Wrap dired--unhide with with-silent-modifications. Thx to Tino Calancha.
+;; 2020/01/26 dadams
+;; Added: bmkp-annotated-cp.
+;; 2020/01/25 dadams
+;; Added: bmkp-edit-bookmark-record-file/buffer.
+;; 2020/01/24 dadams
+;; Added: bmkp-annotate-bookmark-this-file/buffer, bmkp-annotate-all-bookmarks-this-file/buffer.
+;; 2020/01/22 dadams
+;; Added: bmkp-write-alist-bookmarks-to-file, bmkp-save-bookmarks-this-file/buffer,
+;; bmkp-switch-to-bookmark-file-this-file/buffer.
+;; bmkp-switch-bookmark-file-create: Added optional arg SWITCH-TO-LASTP (C-u behavior).
+;; bmkp-save-menu-list-state: Save also last-previous-bookmark-file.
+;; 2020/01/15 dadams
+;; bmkp-specific-files-alist-only: If no FILES arg and buffer is not visiting a file, use ().
+;; 2020/01/12 dadams
+;; Added: bmkp-make-obsolete, bmkp-make-obsolete-variable. Use everywhere instead of vanilla.
+;; bookmark-completing-read, bmkp-completing-read-(1|bookmarks|lax):
+;; Added optional arg USE-NIL-ALIST-P.
+;; bmkp-completing-read-1: Made all args except PROMPT optional.
+;; Protect defvaralias for bmkp-w3m-allow-multi-tabs-flag, for Emacs 20-21.
+;; bookmark-edit-annotation: If no prefix arg, pass non-nil USE-NIL-ALIST-P arg.
+;; bookmark-set: If numeric prefix arg, pass non-nil USE-NIL-ALIST-P arg.
+;; bookmark-show-annotation, bmkp-retrieve-icicle-search-hits-1, bmkp-set-sequence-bookmark:
+;; Pass non-nil USE-NIL-ALIST-P arg.
+;; Renamed bmkp-bookmark-valid-p to bmkp-bookmark-type-valid-p.
+;; bmkp-bookmark-type-valid-p: Restored missing definition (was bmkp-bookmark-type).
+;; 2019/08/13 dadams
+;; Added bmkp-clone-bookmark, bmkp-copy-bookmark (alias).
+;; 2019/07/13 dadams
+;; bookmark-edit-annotation: Added &rest _IGNORED, to accommodate vanilla change for bug #20150.
+;; 2019/06/08 dadams
+;; bmkp-set-kmacro-bookmark: Do not use read-kbd-macro.
+;; bmkp-repeat-command: Same as in zz-repeat-command in zones.el now.
+;; Require repeat.el. Bind repeat-previous-repeated-command.
+;; bmkp-(next|previous)(-*)-bookmark(-*)-repeat: Removed require of repeat.el.
+;; 2019/05/21 dadams
+;; bmkp-dired-remember-*-marks: Updated per dired-remember-marks, for Emacs 27+.
+;; 2019/05/19 dadams
+;; Bind print-gensym wherever we bind print-circle.
+;; 2019/05/11 dadams
+;; Added bmkp-jump-to-list-button button type. Forgot it on 2019-05-02.
+;; 2019/05/09 dadams
+;; bmkp-this-buffer-bmenu-list: Call bookmark-maybe-load-default-file at outset.
+;; 2019/05/02 dadams
+;; Added: bmkp-add-jump-to-list-button.
+;; bmkp-describe-bookmark(-internals): Use bmkp-add-jump-to-list-button.
+;; 2019/05/01 dadams
+;; Added bmkp-jump-to-list.
+;; 2019/04/23 dadams
+;; Added bmkp-annotation-or-bookmark-description, bmkp-propertize.
+;; 2019/04/21 dadams
+;; bmkp-temporary-bookmarking-mode: When enable mode reset bmkp-temporary-bookmarking-mode to nil.
+;; 2019/02/18
+;; bmkp-autofile-bookmark-p, bmkp-file-target-set, bmkp-autofile-add-tags,
+;; bmkp-get-autofile-bookmark:
+;; Handle a directory like a file.
+;; 2018/12/23 dadams
+;; Added: bmkp-bookmark-type-valid-p, bmkp-buffer-bookmark-p, bmkp-buffer-alist-only.
+;; Removed: bmkp-bookmark-type - use bmkp-bookmark-type-valid-p instead.
+;; bmkp-edit-tags-send: Use bmkp-bookmark-type-valid-p.
+;; 2018/11/22 dadams
+;; bookmark-load: Return the list of bookmarks read from FILE.
+;; bmkp-set-izones-bookmark: Include zone EXTRA info in bookmark record.
+;; 2018/11/09 dadams
+;; Removed: bmkp-line-number-at-pos (not used).
+;; 2018/10/10 dadams
+;; Added: bookmark-jump-other-frame.
+;; 2018/09/21 dadams
+;; bmkp-show-this-annotation-read-only, bmkp-edit-this-annotation, bmkp-desktop-read,
+;; bmkp-jump-man, bmkp-jump-dired, bmkp-jump-to-type, bmkp-*-jump, bmkp-jump-in-navlist:
+;; Use bmkp--pop-to-buffer-same-window, not switch-to-buffer.
+;; bmkp-image-jump-other-window, bmkp-autofile-jump-other-window:
+;; Use bmkp-select-buffer-other-window, not switch-to-buffer (typo).
+;; 2018/08/30 dadams
+;; Added defmacro for with-coding-priority at compile time.
+;; 2018/04/24 dadams
+;; Added: bmkp-cycle-eww, bmkp-cycle-eww-other-window, bmkp-next-eww-bookmark,
+;; bmkp-next-eww-bookmark-other-window, bmkp-next-eww-bookmark-other-window-repeat,
+;; bmkp-next-eww-bookmark-repeat, bmkp-previous-eww-bookmark,
+;; bmkp-previous-eww-bookmark-other-window, bmkp-previous-eww-bookmark-other-window-repeat,
+;; bmkp-previous-eww-bookmark-repeat.
+;; 2018/04/22 dadams
+;; Added: bmkp-bookmark-file-load-jump, bmkp-bookmark-file-switch-jump. Not bound to keys.
+;; 2018/02/23 dadams
+;; Changes to EWW support - thx to Charles Roelli.
+;; Added: bmkp-eww-generate-buffer-flag.
+;; Removed: bmkp-jump-eww-in-buffer-*eww*, bmkp-jump-eww-renaming-buffer,
+;; bmkp-eww-sans-pop-to-buffer, bmkp-get-eww-mode-buffer.
+;; Renamed: bmkp-eww-buffer-handling to bmkp-eww-buffer-renaming.
+;; bmkp-eww-new-buf-name and bmkp-eww-jumping-p are now buffer-local.
+;; bmkp-jump-eww: Respect bmkp-eww-generate-buffer-flag. Use buffer-local eww-after-render-hook.
+;; Integrate code from removed functions.
+;; bmkp-eww-rename-buffer: Rename to generated name if rename attempt fails and either
+;; bmkp-eww-generate-buffer-flag or not bmkp-eww-jumping-p.
+;; 2018/02/12 dadams
+;; bookmark-write-file, bmkp-regexp-filtered-bookmark-name-alist-only:
+;; Use bookmark-name-from-full-record, not car.
+;; 2018/02/10 dadams
+;; bookmark-rename: No need to propertize name here - done in call to bookmark-set-name.
+;; bookmark-alist-from-buffer: Use bmkp-bookmark-name-from-record, not car.
+;; 2017/11/27 dadams
+;; bookmark-write-file:
+;; Corrected change made on 2017/01/10 (fix for bug #25365).
+;; Bind Lisp mode hooks to nil, to avoid inserting a Lisp file header for existing empty file.
+;; 2017/10/31 dadams
+;; bookmark-send-edited-annotation: test using following-char, not bmkp-looking-at-p.
+;; bookmark-save: Non-nil FILE now means use FILE, regardless of PARG value.
+;; 2017/10/08 dadams
+;; bmkp-bookmark-description, bmkp-describe-bookmark-internals:
+;; Bind print-(circle|length|level) so pp-to-string prints all.
+;; 2017/07/31 dadams
+;; bmkp-find-file-invoke-bookmark-if-autofile:
+;; Bind bmkp-autofile-access-invokes-bookmark-flag to nil while jumping to the bookmark.
+;; 2017/07/30 dadams
+;; Added: bmkp-autofile-access-invokes-bookmark-flag, bmkp-find-file-invoke-bookmark-if-autofile.
+;; bmkp-get-bookmark-in-alist: Use arg ALIST (was neglected).
+;; 2017/07/19 dadams
+;; Put back bmkp-info-cp, as an obsolete alias, temporarily.
+;; 2017/07/03 dadams
+;; Added: bmkp-info-position-cp, bmkp-info-sort-ignores-directories-flag.
+;; Renamed: bmkp-info-cp to bmkp-info-node-name-cp.
+;; bmkp-sort-comparer: Applied renaming of bmkp-info-cp.
+;; bmkp-info-node-name-cp: Respect bmkp-info-sort-ignores-directories-flag (default: manual names)
+;; 2017/06/26 dadams
+;; Added: bmkp-kmacro-list-bookmark-p.
+;; bmkp-bookmark-description: Handle bmkp-kmacro-list-bookmark-p.
+;; 2017/06/25 dadams
+;; Added: bmkp-set-kmacro-bookmark, bmkp-set-kmacro-list-bookmark, bmkp-jump-kmacro-list,
+;; bmkp-make-kmacro-list-record.
+;; 2017/05/12 dadams
+;; Added: bmkp-eww-auto-bookmark-mode, bmkp-set-eww-bookmark-here, bmkp-toggle-eww-auto-type,
+;; bmkp-eww-auto-type. Thx to Charles Roelli.
+;; 2017/03/31 dadams
+;; Added other-window versions of: bmkp-(next|previous)(TYPE)-bookmark(-repeat).
+;; bmkp-autonamed-bookmark-p:
+;; If BUFFER is nil then let ?B match any name - do not use current buffer for nil case.
+;; bmkp-goto-position: Error now mentions buffer name, not just file.
+;; bmkp-cycle: If empty bmkp-nav-alist ask before setting it to bookmark-alist.
+;; 2017/02/26 dadams
+;; Added:
+;; bmkp-eww-rename-buffer, bmkp-eww-new-buffer-name, bmkp-eww-sans-pop-to-buffer,
+;; bmkp-eww-buffer-handling (was ~bmkp-eww-allow-multiple-buffers-flag),
+;; bmkp-get-eww-mode-buffer, bmkp-eww-jumping-p, bmkp-eww-new-buf-name,
+;; bmkp-jump-eww-in-buffer-*eww* (was ~bmkp-jump-eww-only-one-buffer),
+;; bmkp-jump-eww-renaming-buffer (was ~bmkp-jump-eww-new-buffer), bmkp-info-auto-type,
+;; bmkp-info-auto-bookmark-mode, bmkp-set-info-bookmark-with-node-name,
+;; bmkp-toggle-info-auto-type.
+;; Removed: bmkp-eww-allow-multiple-buffers-flag, bmkp-eww-set-new-buffer-name,
+;; bmkp-jump-eww-new-buffer, bmkp-jump-eww-only-one-buffer.
+;; bmkp-edit-bookmark-name-and-location: Don't consider changed-buffname-p if EWW bookmark.
+;; bmkp-make-eww-record: Use bmkp-eww-new-buffer-name for buffer-name field.
+;; Add bmkp-eww-rename-buffer to hooks eww-after-render-hook and eww-restore-history.
+;; Support EWW only for Emacs 25+, not for 24.4+. (E.g., bmkp-eww-title, bmkp-eww-url).
+;; bookmark-show-all-annotations:
+;; Use bookmark-maybe-load-default-file, to load bookmark file.
+;; For Emacs 24+, call view-mode-enter with no args. Thx to Alan Wehmann for bug report
+;; and Martin Rudalics for info about the new signature.
+;; bmkp-completing-read-1: Use single default, not list, for Emacs 20-22.
+;; bmkp-default-bookmark-name:
+;; Ensure use a single bname, not a list of names returned by bmkp-default-lighted.
+;; 2017/01/29 dadams
+;; Added: bmkp-eww-title, bmkp-eww-url.
+;; bookmark-set, bmkp-this-buffer-p, bmkp-make-eww-record: Use bmkp-eww-title, bmkp-eww-url.
+;; 2017/01/10 dadams
+;; Added:
+;; bmkp-eww-allow-multiple-buffers-flag, bmkp-eww-set-new-buffer-name, bmkp-jump-eww-new-buffer,
+;; bmkp-jump-eww-only-one-buffer.
+;; Renamed: bmkp-replace-eww-keys-flag to bmkp-eww-replace-keys-flag,
+;; bmkp-w3m-allow-multi-tabs-flag to bmkp-w3m-allow-multiple-buffers-flag,
+;; bmkp-jump-w3m-new-session to bmkp-jump-w3m-new-buffer,
+;; bmkp-jump-w3m-only-one-tab to bmkp-jump-w3m-only-one-buffer. Keep old as aliases.
+;; bmkp-jump-eww: Dispatch to bmkp-jump-eww-(new|only-one)-buffer
+;; bmkp-jump-w3m-new-buffer, bmkp-jump-w3m-only-one-buffer: Use get-buffer-create, just in case.
+;; bookmark-write-file:
+;; Updated per latest fix for bug #25365: insert version stamp after writing bmks. UNTESTED.
+;; 2017/01/08 dadams
+;; Use the term "entry", not "property" everywhere, for bookmark entries (fields).
+;; 2017/01/07 dadams
+;; bookmark-write-file, bookmark-load, bmkp-temporary-bookmarking-mode:
+;; Use bookmark-file-coding-system (Emacs bug #25365). UNTESTED.
+;; 2017/01/03 dadams
+;; bookmark-location: Corrected doc string to reflect code: buffer before file.
+;; 2016/12/31 dadams
+;; Added: bmkp-non-invokable-bookmark-p, bmkp-non-invokable-alist-only.
+;; bmkp-bookmark-description: Include non-invokable.
+;; 2016/12/21 dadams
+;; Added: bmkp-ffap-max-region-size, bmkp-ffap-guesser.
+;; bmkp-file-target-set, bmkp-autofile-set, bmkp-autofile-(add|remove)-tags:
+;; Use bmkp-ffap-guesser.bmkp-ffap-guesser, not ffap-guesser.
+;; 2016/12/11 dadams
+;; Added: bmkp-convert-eww-bookmarks, bmkp-replace-eww-keys-flag.
+;; 2016/11/25 dadams
+;; bmkp-make-function-bookmark: Added bookmark-make-record-default, to include creation date.
+;; bmkp-make-sequence-record: Use 0 as position, in record.
+;; bookmark-sort-flag: Replace doc string with mention that it is not used.
+;; 2016/11/23 dadams
+;; bookmark-save, bookmark-write-file, bookmark-load, bmkp-empty-file, bmkp-tags-in-bookmark-file,
+;; bmkp-list-defuns-in-commands-file, bmkp-set-bookmark-file-bookmark, bmkp-desktop-read:
+;; Raise an error if we have a directory, not a file.
+;; 2016/11/18 dadams
+;; Support Emacs 24.[45] too.
+;; bookmark-set, bmkp-this-buffer-p, bmkp-make-eww-record: Update for Emacs 24.[45].
+;; bmkp-edit-bookmark-name-and-location: Add support for EWW.
+;; bmkp-jump-eww: Create buffer *eww* if it does not exist.
+;; bmkp-crosshairs-highlight: Respect bmkp-crosshairs-highlight (not really needed).
+;; bmkp-eww-cp: typos: w3m -> eww.
+;; 2016/11/15 dadams
+;; bmkp-*eww-*, bookmark-set, bmkp-this-buffer-p, bmkp-url-bookmark-p, bmkp-url-target-set,
+;; bmkp-bookmark-description: Ensure that EWW code is only for Emacs 25+.
+;; 2016/11/14 dadams
+;; Added: bmkp-eww-jump, bmkp-eww-jump-other-window, bmkp-eww-alist-only, bmkp-eww-bookmark-p,
+;; bmkp-eww-cp, bmkp-jump-eww, bmkp-make-eww-record, bmkp-eww-history.
+;; bmkp-non-file-filename: Added EWW entry.
+;; bookmark-set, bmkp-this-buffer-p, bmkp-url-bookmark-p, bmkp-url-target-set,
+;; bmkp-bookmark-description: Support eww-mode.
+;; bmkp-url-jump(-other-window): Just use bmkp-url-alist-only.
+;; 2016/10/27 dadams
+;; bmkp-end-position-post-context: Typo: (point) -> ereg.
+;; 2016/09/21 dadams
+;; Added: bmkp-desktop-default-directory.
+;; Added: desktop-full-file-name, for Emacs < 22.
+;; bmkp-set-desktop-bookmark, bmkp-desktop-change-dir, bmkp-desktop-read:
+;; Use bmkp-desktop-default-directory when reading or expanding file name.
+;; bmkp-desktop-change-dir: Error in interactive spec too, if cannot load desktop.el.
+;; 2016/09/10 dadams
+;; Added: bmkp-format-spec.
+;; bmkp-autoname-format: Use %B in default value. Update doc string, allowing %B.
+;; bmkp-autonamed-bookmark-p: Added optional arg BUFFER. Use bmkp-format-spec.
+;; bmkp-autonamed-bookmark-for-buffer-p, bmkp-autonamed-this-buffer-bookmark-p:
+;; Use bmkp-autonamed-bookmark-p.
+;; 2016/09/06 dadams
+;; Added: bmkp-read-from-whole-string.
+;; bmkp-make-function-bookmark, bmkp-set-sequence-bookmark: Use bmkp-read-from-whole-string.
+;; 2016/06/23 dadams
+;; bmkp-remove-all-tags, bmkp-add-tags, bmkp-set-tag-value, bmkp-remove-tags,
+;; bmkp-paste-(add|paste)-tags, bmkp-autofile-add-tags:
+;; Corrected doc string to say also that NO-UPDATE-P does not update mod count.
+;; bookmark-store, bookmark-set, bookmark-relocate, bmkp-(url|file)-target-set,
+;; bmkp-autofile-set, bmkp-autofile-remove-tags:
+;; Renamed arg NO-UPDATE-P to NO-REFRESH-P.
+;; 2016/06/21 dadams
+;; bmkp-edit-bookmark-records-send, bmkp-set-tag-value-for-bookmarks, bmkp-rename-tag,
+;; bmkp-delete-bookmarks:
+;; Put bookmark-save-flag let-binding around iteration only, so modification is recorded etc.
+;; 2016/05/30 dadams
+;; bmkp-not-near-other-auto-idle-bmks: Corrected typo: test distance for POSITION, not point.
+;; 2016/04/23 dadams
+;; Added: bmkp-set-dired-bookmark-for-files.
+;; 2015/10/31 dadams
+;; bookmark-import-new-list: Added arg RETURN-BMKS: Return bookmarks added, if non-nil.
+;; 2015/09/07 dadams
+;; bmkp-some: Return cons (ELEMENT . VALUE).
+;; 2015/08/16 dadams
+;; Renamed bmkp-set-restrictions-bookmark to bmkp-set-izones-bookmark.
+;; Renamed wide-n.el stuff to zones.el stuff.
+;; 2015/08/13 dadams
+;; Removed: bmkp-readable-marker.
+;; bmkp-set-restrictions-bookmark:
+;; Added optional args. A prefix arg prompts for VARIABLE. Use wide-n-readable-marker.
+;; 2015/08/12 dadams
+;; bmkp-set-restrictions-bookmark: Update for new wide-n format.
+;; 2015/08/10 dadams
+;; bmkp-set-restrictions-bookmark:
+;; Added missing comma, to eval end marker. Corrected END: caddr now, not cddr.
+;; 2015/08/06 dadams
+;; bmkp-some: Fixed yesterday's fix. ;-)
+;; 2015/08/05 dadams
+;; bmkp-some: Fixed so it returns the first list element for which the predicate is true.
+;; 2015/07/31 dadams
+;; bmkp-set-restrictions-bookmark: Use new wide-n-restrictions format: (NUM BEG END).
+;; 2015/06/26 dadams
+;; Added: bmkp-function-alist-only.
+;; 2015/06/18 dadams
+;; bmkp-bookmark-description: Print location, if present, for non-file bmk. Thx Martin Oppegaard.
+;; bookmark-location: Reordered - prefer buffer name to file name.
+;; 2015/06/17 dadams
+;; bmkp-bookmark-description: Added another \t for URL:.
+;; 2015/06/15 dadams
+;; Allow for POSITION in bookmarks to be nil or absent - updated bookmark-default-handler,
+;; bmkp-region-bookmark-p, bmkp-handle-region-default, bmkp-goto-position, bmkp-jump-dired,
+;; bmkp-not-near-other-auto-idle-bmks.
+;; 2015/05/23 dadams
+;; bookmark-load: Reset bmenu stuff: bmkp-bmenu-marked-bookmarks, bmkp-modified-bookmarks,
+;; bmkp-flagged-bookmarks, bmkp-bmenu-omitted-bookmarks, bmkp-bmenu-filter-function.
+;; 2015/04/24 dadams
+;; bookmark-set: Clarified doc string wrt bookmarks that have the same name.
+;; 2015/04/13 dadams
+;; bmkp-temporary-bookmarking-mode:
+;; Have to do bookmark-insert-file-format-version-stamp here, because make-temp-file creates the
+;; file, so it satisfies file-exists-p for bookmark-write-file.
+;; 2015/04/10 dadams
+;; bmkp-remove-all-tags, bmkp-add-tags, bmkp-remove-tags:
+;; Do not call bmkp-maybe-save-bookmarks if NO-UPDATE-P.
+;; bmkp-set-tag-value-for-(navlist|bookmarks): Added optional arg MSG-P.
+;; bmkp-set-tag-value-for-bookmarks:
+;; Call bmkp-tags-list, bmkp-maybe-save-bookmarks, and bmkp-refresh/rebuild-menu-list.
+;; bmkp-set-tag-value:
+;; Pass non-nil NO-UPDATE-P to bmkp-add-tags. Unless NO-UPDATE-P, call bmkp-tags-list,
+;; bmkp-maybe-save-bookmarks, and bmkp-refresh/rebuild-menu-list.
+;; bmkp-remove-tags-from-all: Call bmkp-maybe-save-bookmarks and bmkp-refresh/rebuild-menu-list.
+;; bmkp-rename-tag, bmkp-purge-notags-autofiles: Call bmkp-maybe-save-bookmarks.
+;; 2015/03/23 dadams
+;; bookmark-show-all-annotations: When in Bookmark List buffer, respect the sort order.
+;; 2015/02/24 dadams
+;; bmkp-get-autofile-bookmark: Corrected 2015-02-15 fix - ensure BDIR is non-nil too, before test.
+;; 2015/02/22 dadams
+;; Moved here from bookmark+-bmu.el:
+;; bmkp-reset-bmkp-store-org-link-checking-p, bmkp-store-org-link-checking-p.
+;; Advice of org-store-link (not needed for bmkp-bmenu-store-org-link).
+;; bmkp-store-org-link(-1): Link type changed from bookmark-other-window to bookmark-other-win.
+;; bookmark-prop-set: Added optional arg DONT-UPDATE-NAME.
+;; Update bmkp-full-record property on bookmark name, unless DONT-UPDATE-NAME.
+;; bmkp-record-visit, bmkp-save-new-region-location, bmkp-goto-position:
+;; Use arg DONT-UPDATE-NAME in sequence of calls to bookmark-prop-set.
+;; 2015/02/21 dadams
+;; Added: bmkp-store-org-link, bmkp-store-org-link-1.
+;; 2015/02/15 dadams
+;; bmkp-get-autofile-bookmark: Corrected test for same file to use absolute file names.
+;; bmkp-read-bookmark-file-default: .emacs.bmk -> ~/.emacs.bmk.
+;; 2015/02/11 dadams
+;; Added (redefinition of) bookmark-insert-current-bookmark for Emacs 24.3+.
+;; 2015/02/08 dadams
+;; Added: bmkp-properties-to-keep, bmkp-tagged-alist-only, bmkp-untagged-alist-only.
+;; Renamed: bmkp-icicle-* to bmkp-icicles-*.
+;; bmkp-this-buffer-bmenu-list, bmkp-navlist-bmenu-list: Restore original values in case of error.
+;; bookmark-set: Do not overwrite properties listed in option bmkp-properties-to-keep.
+;; bmkp-prompt-for-tags-flag: Updated doc string wrt adding, not replacing.
+;; bmkp-autofile-filecache: Corrected autoload cookie (typo).
+;; 2015/02/05 dadams
+;; bookmark-insert-annotation: BOOKMARK can be a bookmark or its name.
+;; 2015/02/03 dadams
+;; bmkp-occur-target-set: Removed unused let-binding.
+;; 2015/01/28 dadams
+;; Added: bookmark-automatically-show-annotations, bmkp-show-this-annotation-read-only,
+;; bmkp-edit-this-annotation.
+;; Soft-require font-lock+.el.
+;; bookmark-insert-annotation: Convert BOOKMARK input to its name.
+;; bookmark-edit-annotation-mode: Bind key C-x C-q to bmkp-show-this-annotation-read-only.
+;; bookmark-show-annotation-mode: Bind key C-x C-q to bmkp-edit-this-annotation.
+;; bookmark-show-annotation:
+;; If bookmark-automatically-show-annotations = edit then just call bookmark-edit-annotation.
+;; Fix title highlighting (need font-lock+.el) and buffer-modified-p.
+;; Set bookmark-annotation-name. Use `, not ', in title.
+;; bookmark-edit-annotation: Manage buffer-modified-p.
+;; 2015/01/17 dadams
+;; Added bmkp-annotate-bookmark.
+;; bookmark-show-annotation, bookmark-show-all-annotations: Made it interactive.
+;; 2015/01/01 dadams
+;; bookmark-default-handler, bmkp-goto-position:
+;; Do not bind enable-local-variables to nil - the visit is not hidden and temporary.
+;; 2014/12/18 dadams
+;; bmkp-this-file-bmenu-list: Restore vars if error.
+;; 2014/12/16 dadams
+;; bmkp-last-specific-file-p: Use bmkp-same-file-p, not string=.
+;; 2014/12/15 dadams
+;; Added: bmkp-non-dir-file-jump, bmkp-non-dir-file-jump-other-window,
+;; bmkp-local-non-dir-file-jump, bmkp-local-non-dir-file-jump-other-window,
+;; bmkp-remote-non-dir-file-jump, bmkp-remote-non-dir-file-jump-other-window,
+;; bmkp-non-dir-file-alist-only, bmkp-non-dir-file-bookmark-p,
+;; bmkp-local-non-dir-file-alist-only, bmkp-local-non-dir-file-bookmark-p,
+;; bmkp-remote-non-dir-file-alist-only, bmkp-remote-non-dir-file-bookmark-p.
+;; bmkp-autotemp-bookmark-predicates: Added bmkp(-local|-remote)-non-dir-file-bookmark-p.
+;; 2014/11/15 dadams
+;; Added: bmkp-region-jump-narrow-indirect-other-window, bmkp-handle-region+narrow-indirect.
+;; bmkp-jump-man: Updated for Emacs 24+, where Man-getpage-in-background returns process buffer.
+;; 2014/11/14 dadams
+;; bmkp-jump-1: Made arg FLIP-USE-REGION-P optional. Corrected doc string for it: it flips.
+;; bmkp-snippet-to-kill-ring, bmkp-autonamed-*jump*, bmkp-temporary-jump*, bmkp-w32-browser-jump,
+;; bmkp-variable-list-jump, bmkp-autofile-jump*: Removed FLIP arg (optional).
+;; bmkp-region-jump*: Bind bmkp-use-region to t, and don't pass FLIP arg to bmkp-jump-1.
+;; 2014/11/10 dadams
+;; Added: bookmark-show-annotation-mode, (redefinition of) bookmark-default-annotation-text.
+;; Renamed: bmkp-edit-annotation-mode-inherit-from to bmkp-annotation-modes-inherit-from.
+;; bookmark-show-annotation: Call bookmark-show-annotation-mode, not view-mode-enter.
+;; bookmark-edit-annotation-mode:
+;; Use literal C-c C-M-c, since bookmark-send-edited-annotation is also bound to C-c C-c.
+;; 2014/11/09/dadams
+;; Added: bmkp-get-external-annotation, bmkp-visit-external-annotation.
+;; bookmark-show-annotation: If the annotation is external then jump to its destination.
+;; 2014/11/08 dadams
+;; bmkp-bookmark-description: Corrected formatting for search-hits-p.
+;; 2014/10/28 dadams
+;; Added: option bmkp-edit-annotation-mode-inherit-from.
+;; bookmark-edit-annotation-mode: Redefined to use define-derived-mode (per Emacs 25).
+;; Use new option bmkp-edit-annotation-mode-inherit-from.
+;; bookmark-send-edited-annotation: Allow derived mode (per Emacs 25).
+;; bookmark-edit-annotation:
+;; Call bookmark-insert-annotation. Set local var bookmark-annotation-name to arg (per E25).
+;; 2014/10/27 dadams
+;; Added: Redefinition of bookmark-insert-annotation.
+;; bookmark-edit-annotation-mode: Use bookmark-insert-annotation.
+;; 2014/08/22 dadams
+;; bmkp-desktop-file-p: Redefined to not visit the file: use insert-file-contents-literally.
+;; Added (not (file-directory-p filename)) condition.
+;; 2014/08/21 dadams
+;; Added: bmkp-annotated-bookmark-p.
+;; bmkp-autofile-alist-only: Use bmkp-annotated-bookmark-p.
+;; bmkp-completing-read-1: Bind icicle-bookmark-completing-p.
+;; bmkp-file-this-dir-bookmark-p: Return nil if BOOKMARK is not a bookmark.
+;; Use bmkp-same-file-p, not equal.
+;; 2014/08/19 dadams
+;; Added: bmkp-dired-wildcards-alist-only, bmkp-navlist-bookmark-p.
+;; 2014/08/18 dadams
+;; bmkp-this-file-p: Return nil (instead of raising error) if THIS-FILE is nil.
+;; 2014/07/11 dadams
+;; bookmark-load: Do not customize-save-variable if no change to bmkp-last-as-first-bookmark-file.
+;; bmkp-new-bookmark-default-names: Use setq, not push, for Emacs 20.
+;; 2014/07/06 dadams
+;; Renamed: bmkp-show-end-of-region, bmkp-w3m-allow-multi-tabs to *-flag.
+;; 2014/07/05 dadams
+;; bookmark-write-file: List in file could be (), in which case cannot search backward for \n).
+;; bmkp-read-bookmark-for-type: Added optional PROMPT arg.
+;; bmkp-jump-snippet: Provide PROMPT to bmkp-read-bookmark-for-type. Better msg.
+;; 2014/07/03 dadams
+;; Added: bmkp-read-bookmark-file-default.
+;; Added redefinition of bookmark-import-new-list, bookmark-maybe-rename.
+;; bookmark-load: Do not set blist to value of bookmark-import-new-list.
+;; bookmark-alist-from-buffer: Added optional arg do-not-propertize-p. (Not used anywhere yet.)
+;; bookmark-save: Use bmkp-read-bookmark-file-default.
+;; bookmark-write-file:
+;; Added optional arg ADD. Do not kill FILE buffer if it existed prior to invoking function.
+;; Promoted inner let-bindings print-length etc.
+;; Delete contents only if file does not exist (just in case). Else *-maybe-upgrade-file-format.
+;; Do not delete region if ADD. Position point depending on ADD.
+;; bookmark-write-file, bookmark-default-handler, bmkp-save-menu-list-state, bmkp-goto-position,
+;; bmkp-compilation-target-set:
+;; Let-bind enable-local-variables around find-file-noselect.
+;; bmkp-read-bookmark-file-name: Just pass DEFAULT-FILENAME to read-file-name.
+;; bmkp-empty-file: Pass nil ADD arg to bookmark-write-file.
+;; 2014/06/29 dadams
+;; Added: bmkp-before-jump-hook, bmkp-desktop-save, bmkp-desktop-save-as-last,
+;; bmkp-desktop-current-file, bmkp-desktop-jump-save-before-flag.
+;; bmkp-jump-1: Run bmkp-before-jump-hook.
+;; bmkp-set-desktop-bookmark: Use bmkp-desktop-save.
+;; bmkp-desktop-jump: If bmkp-desktop-jump-save-before-flag then bmkp-desktop-save-as-last.
+;; bmkp-desktop-kill: Updated for Emacs 24.4+.
+;; 2014/06/21 dadams
+;; Added: bmkp-icicle-search-hits-alist-only, bmkp-icicle-search-hits-bookmark-p,
+;; bmkp-icicle-search-hits-retrieve-more, bmkp-jump-icicle-search-hits,
+;; bmkp-retrieve-icicle-search-hits, bmkp-retrieve-more-icicle-search-hits,
+;; bmkp-retrieve-icicle-search-hits-1, bmkp-set-icicle-search-hits-bookmark,
+;; bmkp-make-icicle-search-hits-record, bmkp-unpropertized-string.
+;; bmkp-bookmark-description: Handle Icicles search hits.
+;; 2014/05/30 dadams
+;; bmkp-set-restrictions-bookmark: Updated for new restrictions format (wide-n.el).
+;; 2014/05/27 dadams
+;; bmkp-describe-bookmark(-internals), bmkp-list-defuns-in-commands-file:
+;; Use bmkp-with-help-window, not with-output-to-temp-buffer (Emacs 24.4+ silliness).
+;; 2014/04/05 dadams
+;; Removed bmkp-create-dired-bookmarks-recursive:
+;; Moved to dired+.el and renamed diredp-do-bookmark-dirs-recursive.
+;; 2014/04/02 dadams
+;; bmkp-paste-replace-tags: Added Note to doc string about pasting an empty list of tags.
+;; 2014/03/23 dadams
+;; bmkp-file-target-set: Fix interactive spec (parens).
+;; bmkp-file-target-set, bmkp-autofile-set, bmkp-autofile-(add|remove)-tags:
+;; Soft-require ffap.el before using ffap-guesser.
+;; 2014/03/10 dadams
+;; bookmark-write-file:
+;; Remove prop face & Icicles props, anyway (but not bothering for sequence entry of seq bmks).
+;; bookmark-write-file, bmkp-edit-tags, bmkp-save-menu-list-state, bmkp-readable-p:
+;; Bind print-circle to bmkp-propertize-bookmark-names-flag, not t, to avoid string reuse.
+;; 2014/03/07 dadams
+;; bookmark-exit-hook-internal: Do not raise error, since this is on kill-emacs-hook.
+;; Bug reported: http://superuser.com/q/726057/250462.
+;; 2014/01/02 dadams
+;; Reverted yesterday's change. Just use cond instead of case.
+;; 2014/01/01 dadams
+;; Added bmkp-file-cache-ad-hack, as workaround for macro case not getting byte-compiled.
+;; file-cache-add-file: Use bmkp-file-cache-ad-hack. Thx to Michael Heerdegen.
+;; 2013/11/21 dadams
+;; bmkp-url-target-set: Added argument NO-OVERWRITE-P.
+;; bmkp-(url|file)-target-set: Numeric prefix arg means do not overwrite. N<0 means use full name.
+;; 2013/11/05 dadams
+;; Added: bmkp-create-dired-bookmarks-recursive.
+;; bookmark-set: Added optional arg NO-UPDATE-P - pass it to bookmark-store.
+;; 2013/10/29 dadams
+;; Added: bmkp-pop-to-readable-marker, bmkp-readable-marker, bmkp-bookmark-set-confirm-overwrite,
+;; bmkp-bookmark-set-confirms-overwrite-p.
+;; bookmark-set: Ask for overwrite confirmation if plain prefix arg and bookmark exists.
+;; bmkp-menu-bar-set-bookmark: Use bmkp-bookmark-set-confirm-overwrite, not bookmark-set.
+;; 2013/10/07 dadams
+;; bmkp-edit-bookmark-records-send: Move to line of current bmk, if only one.
+;; 2013/08/09 dadams
+;; Added: bmkp-read-bookmark-file-hook, bmkp-desktop-file-p.
+;; Renamed: bmkp-printable-p to bmkp-readable-p.
+;; bmkp-readable-p: Treat string with no text props separately.
+;; bookmark-alist: Updated doc string.
+;; bookmark-send-edited-annotation: looking-at -> bmkp-looking-at-p (new).
+;; bookmark-load: Update blist with bookmark-import-new-list.
+;; Run bmkp-read-bookmark-file-hook after reading the bookmark file.
+;; bmkp-set-desktop-bookmark: Added prefix arg: sets bookmark without saving desktop file.
+;; 2013/07/24 dadams
+;; bmkp-new-bookmark-default-names, bookmark-make-record-default:
+;; Test using (region-beginning|end), not mark function (C code and simpler).
+;; 2013/07/11 dadams
+;; bmkp-url-target-set: Use let* with backquote lambda instead of lexical-let*.
+;; 2013/07/02 dadams
+;; bmkp-snippet-bookmark-p: Typo: bmkp-snippet-to-kill-ring -> bmkp-jump-snippet.
+;; bmkp-bookmark-description: Include snippet text in bookmark description (help).
+;; 2013/07/01 dadams
+;; bookmark-make-record-default: Fixed typo for end-position (listify).
+;; bmkp-set-snippet-bookmark: Prefix arg now prompts for bookmark name.
+;; 2013/06/30 dadams
+;; Added: bmkp-set-snippet-bookmark, bmkp-snippet-to-kill-ring, bmkp-jump-snippet,
+;; bmkp-snippet-alist-only, bmkp-snippet-bookmark-p, bmkp-snippet-history.
+;; bmkp-autotemp-bookmark-predicates, bmkp-types-alist, bmkp-bookmark-type,
+;; bmkp-bookmark-description:
+;; Cover snippet bookmarks too.
+;; bookmark-make-record-default:
+;; Added optional arg NO-REGION. If non-nil then do not include end-position.
+;; Set NO-CONTEXT to nil for Emacs < 24. Do not calculate FCS, RCS, FCRS, ECRS if NO-CONTEXT.
+;; bmkp-make-(gnus|sequence|desktop|bookmark-file|variable-list)-record:
+;; Pass NO-REGION to bookmark-make-record-default.
+;; 2013/06/29 dadams
+;; Added: bmkp-read-regexp, bmkp-find-tag-default-as-regexp.
+;; Use bmkp-read-regexp, not read-string, everywhere for reading a regexp.
+;; bmkp-bookmark-description: Ensure FILE is non-nil before using it.
+;; 2013/06/10 dadams
+;; bmkp-set-sequence-bookmark: Typo - bookmark-get-bookmarkp -> bookmark-get-bookmark.
+;; 2013/06/02 dadams
+;; bmkp-set-sequence-bookmark: Forgot to bind FUN. Thx to Michael Heerdegen.
+;; 2013/05/31 dadams
+;; bmkp-save-menu-list-state: Display warning, do not raise error, if write-file fails.
+;; bookmark-write-file: Use display-warning, if fboundp.
+;; 2013/05/28 dadams
+;; Renamed: bmkp-edit-bookmark-name-and-file to bmkp-edit-bookmark-name-and-location.
+;; bmkp-edit-bookmark-name-and-location: Handle location property, urls.
+;; bmkp-jump-w3m-new-session, bmkp-jump-w3m-only-one-tab: Use location property, not filename.
+;; Thx to Michael Heerdegen.
+;; 2013/05/15 dadams
+;; bmkp-*-alist-only: Make sure we call bookmark-maybe-load-default-file.
+;; Moved bmkp-string-match-p to bookmark+-bmu.el.
+;; Use bmkp-string-match-p instead of string-match wherever appropriate.
+;; 2013/05/12 dadams
+;; Added: bmkp-write-bookmark-file-hook.
+;; bookmark-write-file: Run bmkp-bookmark-write-file-hook functions after writing.
+;; 2013/04/19 dadams
+;; bookmark-exit-hook-internal: Removed test for non-empty bookmark-alist (Emacs bug #13972).
+;; 2013/04/15 dadams
+;; bmkp-set-sequence-bookmark: Corrected case of adding one sequence to another.
+;; bookmark-write-file: Corrected write-out of sequence bookmarks.
+;; bookmark-alist-from-buffer: Better error message if read error.
+;; 2013/04/14 dadams
+;; Added: bmkp-wrap-bookmark-with-last-kbd-macro, bmkp-dired-remember-*-marks.
+;; bookmark-write-file: If not saving propertized, remove text props for bmks in sequence bmk.
+;; bmkp-edit-bookmark-record-send:
+;; Raise error if bmkp-edit-bookmark-record-send was somehow reset to nil.
+;; Do not reset bmkp-edit-bookmark-orig-record if read error.
+;; bmkp-make-function-bookmark:
+;; Prefix arg means use last-kbd-macro instead of prompting for FUNCTION.
+;; Use read-from-whole-string, not read, to convert name to symbol.
+;; If FUNCTION is a function or vector, do not convert it.
+;; bmkp-bookmark-description: For sequence-p, remove properties from each bmk name in sequence.
+;; Define bmkp-bookmark-name-from-record (no longer a defalias) with an optional UNPROPERTIZE arg.
+;; bmkp-make-dired-record: Use bmkp-dired-remember-*-marks, not dired-remember-marks.
+;; FUNCTION can now be a vector (a keyboard macro). Use read-from-whole-string, not read.
+;; bmkp-jump-function: If function property is a vector, invoke it as a keyboard macro.
+;; bmkp-set-sequence-bookmark:
+;; Prefix ARG now allows for replace, in addition to append and prepend. No replace question.
+;; A BOOKMARK-NAMES item can now be a bookmark, a function, or keyboard macro - or its name.
+;; A BOOKMARK-NAMES item that is itself a sequence has its bookmarks spliced in.
+;; Use lax as value of NAMES-ONLY-P to bmkp-completing-read-bookmarks.
+;; 2013/04/12 dadams
+;; Added: bmkp-sequence-alist-only.
+;; bmkp-set-sequence-bookmark: Added prefix arg PREPENDP. Use bmkp-completing-read-lax.
+;; Use \\<bmkp-edit-bookmark-record-mode-map> in doc strings with *-record-send.
+;; bookmark-get-bookmark: A cons must also have a string car, to tell a bmk from a list of bmks.
+;; bmkp-make-function-bookmark: Use bmkp-completing-read-lax for BOOKMARK-NAME.
+;; 2013/04/10 dadams
+;; Added: bmkp-set-sequence-bookmark, bmkp-make-sequence-record, bmkp-completing-read-bookmarks.
+;; bmkp-completing-read-1:
+;; Do not put DEFAULT in PROMPT if DEFAULT is "". Removed useless let-binding of DEFAULT.
+;; Removed unnecessary final massaging of STR.
+;; bookmark-completing-read: Mention in doc string that nil DEFAULT means return "".
+;; 2013/03/29 dadams
+;; bmkp-toggle-saving-bookmark-file: If neither is nil, set *-last-* to nil before toggling.
+;; 2013/03/17 dadams
+;; bmkp-bmenu-list-1: Do not toggle filenames unless bookmark-alist is defined (Emacs bug #13972).
+;; 2013/01/07 dadams
+;; bmkp-remove-all-tags, bmkp(-autofile)-(add|remove)-tags, bmkp-set-tag-value,
+;; bmkp-paste-(add|replace)-tags, bmkp-(url|file)-target-set, bmkp-autofile-set:
+;; Added missing NO-UPDATE-P arg for interactive spec.
+;; bmkp-remove-all-tags: Moveed msg to the end.
+;; bmkp-paste-replace-tags: Added sleep-for after first msg.
+;; 2012/11/13 dadams
+;; bmkp-sorting-description: Fixed 1st case: use ORDER only if bmkp-sort-comparer is also non-nil.
+;; 2012/11/11 dadams
+;; Added: bmkp-sorting-description (factored out from bmkp-msg-about-sort-order).
+;; bmkp-msg-about-sort-order: Use bmkp-sorting-description.
+;; bmkp-current-sort-order: Return nil if bmkp-sort-comparer is not in bmkp-sort-orders-alist.
+;; 2012/11/09 dadams
+;; Added: bmkp-autofile-filecache.
+;; Added defadvice for file-cache-add-file.
+;; bookmark-store, bmkp-url-target-set: Added optional arg NO-UPDATE-P.
+;; bookmark-set, bmkp-make-function-bookmark, bmkp-url-target-set, bmkp-file-target-set:
+;; Adjusted calls to bookmark-store to accommodate NO-UPDATE-P arg.
+;; bmkp-make-record-for-target-file:
+;; Add CREATED property for all bookmark types. Factor out the common stuff.
+;; Remove any text properties from FILE arg before using it.
+;; 2012/10/09 dadams
+;; Made all autoload cookies explicitly load bookmark+.el(c). Should help ELPA (e.g. MELPA).
+;; 2012/10/01 dadams
+;; bmkp-thing-at-point: Updated per icicle-thing-at-point. Thx to Joe Bloggs.
+;; 2012/09/29 dadams
+;; Added redefinition of bookmark-version-control.
+;; bookmark--jump-via:
+;; When bmkp-use-w32-browser-p, just handle, do after-jump hook & jump-fn, and show annotation.
+;; bookmark-handle-bookmark:
+;; When bmkp-use-w32-browser-p, just invoke w32-browser and throw to bookmark--jump-via.
+;; bookmark-write-file: Use find-file-noselect.
+;; bmkp-save-menu-list-state:
+;; Bind print-circle, version-control, require-final-new-line. Use find-file-noselect.
+;; Copy shared bookmark lists and single strings, to avoid circular refs.
+;; Raise error, not just msg, if file-error.
+;; bookmark-write-file: Bind require-final-newline.
+;; 2012/09/26 dadams
+;; bmkp-save-menu-list-state: Use write-file, not write-region, so backups are made.
+;; 2012/09/24 dadams
+;; bookmark-write-file: Use write-file, not write-region, so backups are made. Emacs bug #12507.
+;; 2012/09/22 dadams
+;; bookmark-set: Updated handling of bmkp-auto-light-when-set for (non-)autonamed-in-buffer.
+;; bmkp-autonamed-this-buffer-bookmark-p: Require that the buffer name part match also.
+;; bmkp-autonamed-this-buffer-alist-only: Corrected to use bmkp-autonamed-this-buffer-bookmark-p.
+;; 2012/09/11 dadams
+;; bmkp-set-autonamed-bookmark-at-line: Use prefix arg for line no. Use line-beginning-position.
+;; 2012/09/06 dadams
+;; Added: bmkp-string-match-p.
+;; 2012/08/28 dadams
+;; bookmark-send-edited-annotation: Record an empty annotation as nil, not "".
+;; 2012/08/21 dadams
+;; Call tap-put-thing-at-point-props after load thingatpt+.el.
+;; 2012/08/18 dadams
+;; Invoke tap-define-aliases-wo-prefix if thingatpt+.el is loaded.
+;; Added: bmkp-thing-at-point.
+;; thing-at-point -> bmkp-thing-at-point, everywhere.
+;; 2012/08/10 dadams
+;; Info-bookmark-make-record: Updated wrt Emacs 24.
+;; Renamed: old-bookmark-insert to bmkp-ORIG-bookmark-insert.
+;; 2012/07/04 dadams
+;; bmkp-create-variable-list-bookmark: Removed INTERACTIVEP arg to bookmark-set.
+;; #'(lambda...) -> (lambda...).
+;; 2012/07/02 dadams
+;; bmkp-default-handler-for-file:
+;; Reverted 2012/05/04 change to use lexical-let. Byte code in saved bookmark was problematic.
+;; 2012/06/26 dadams
+;; Wrapped require of bookmark+-mac.el in eval-when-compile.
+;; 2012/06/21 dadams
+;; Try to load-library bookmark+-mac. Require it only if cannot load-library.
+;; 2012/06/12 dadams
+;; bmkp-new-bookmark-default-names: 1. Test for DEFS at end is listp, not consp. 2. Return FNS.
+;; bmkp-completing-read-1: Removed empty-input loop - caller must provide a default or handle "".
+;; 2012/06/1 dadams
+;; bookmark-make-record: Replace an empty bookmark name with <EMPTY NAME>.
+;; bookmark-set, bmkp-completing-read-1: Require user to input a non-empty bookmark name.
+;; bmkp-bookmark-name-member: If NAME is null, just use member. Skip any in NAMES that is null.
+;; 2012/05/16 dadams
+;; Added: bmkp-string-less-case-fold-p.
+;; bmkp-list-all-tags: List tags alphabetically. Thx to Anders Johansson for the suggestion.
+;; 2012/05/05 dadams
+;; bookmark-store, bmkp-make-function-bookmark, bmkp-unomit-all, bmkp-url-target-set:
+;; Added optional arg NO-MSG-P.
+;; bookmark-store, bookmark-set, bmkp-record-visit, bmkp-make-function-bookmark,
+;; bmkp-current-bookmark-list-state, bmkp-unomit-all, bmkp-url-target-set, bmkp-file-target-set,
+;; bmkp-replace-existing-bookmark:
+;; Pass NO-MSG-P to *-refresh/rebuild-menu-list, *-surreptitiously-rebuild-list, *-store.
+;; 2012/05/04 dadams
+;; bmkp-remove-tags, bmkp-all-tags(-regexp)-alist-only
+;; bmkp(-(auto)file(-this-dir))(-(all|some)-tags)(-regexp)-alist-only,
+;; bmkp-specific-(buffers|files)-alist-only, bmkp-sort-omit, bmkp-url-target-set,
+;; bmkp-autofile-remove-tags. bmkp-default-handler-for-file, bmkp-set-bookmark-file-bookmark,
+;; bmkp-set-desktop-bookmark, bmkp-set-variable-list-bookmark,
+;; bmkp-create-variable-list-bookmark, bmkp-jump-dired,
+;; bmkp-find-file-(all|some)-tags(-regexp)(-other-window):
+;; Use lexical-let(*), to get closures for free vars in lambdas.
+;; bmkp-regexp-filtered-(file-name|tags)-alist-only: Moved let inside lambda.
+;; bmkp-make-dired-record: Use car instead of (lambda (x) (car x)).
+;; 2012/05/01 dadams
+;; Added: bmkp-tagged-bookmark-p (alias), bmkp-tagged-cp.
+;; bmkp-(add|remove)-tags: Return negative nb-* if changed from (un)tagged to not (un)tagged.
+;; bmkp-paste-replace-tags: Do not call bmkp-remove-all-tags unless there are tags to remove.
+;; 2012/04/27 dadams
+;; bmkp-edit-(tags|bookmark-record): Use bmkp-with-output-to-plain-temp-buffer.
+;; 2012/04/18 dadams
+;; Do not try to define bmkp-global-auto-idle-bookmark-mode for Emacs 21 (no define-globalized*).
+;; 2012/04/16 dadams
+;; bmkp-bookmark-description: List tags as strings on separate lines.
+;; Add newline after annotation.
+;; 2012/04/13 dadams
+;; Added: bmkp-(flagged|modified)-bookmark-p, bmkp-(flagged|modified)-cp.
+;; bookmark-store, bookmark-set-name, bookmark-prop-set, bmkp-edit-bookmark-record(s)-send,
+;; bmkp-replace-existing-bookmark, bmkp-delete-bookmarks:
+;; Use (equivalent of) eq version of add-to-list.
+;; 2012/04/10 dadams
+;; Added: bmkp-count-multi-mods-as-one-flag.
+;; bmkp-edit-bookmark-records-send, bmkp-set-tag-value-for-bookmarks, bmkp-remove-tags-from-all,
+;; bmkp-rename-tag, bmkp-purge-notags-autofiles,
+;; bmkp-delete(-all)-autonamed(-for)(-this-buffer)(-no-confirm), bmkp-delete-bookmarks,
+;; bmkp-delete(-all)-temporary(-bookmarks|-no-confirm):
+;; Corrected bookmark-save to bookmark-save-flag in bindings to nil.
+;; Use bmkp-count-multi-mods-as-one-flag for the binding.
+;; 2012/04/09 dadams
+;; bookmark-relocate, bmkp-edit-bookmark-records-send, bmkp-set-tag-value, bmkp-file-target-set,
+;; bmkp-autofile-set:
+;; Added optional arg NO-UPDATE-P. Use it to inhibit display refreshing.
+;; bmkp-edit-bookmark-records-send, bmkp-set-tag-value-for-bookmarks, bmkp-remove-tags-from-all,
+;; bmkp-rename-tag, bmkp-purge-notags-autofiles, delete-all-autonamed-for-this-buffer
+;; bmkp-delete(-all)-temporary-(bookmarks|no-confirm), bmkp-delete-bookmarks,
+;; bmkp-delete-autonamed(-this-buffer)(-no-confirm):
+;; Bind bookmark-save to nil around iteration, to inhibit saving until finished.
+;; bmkp-(add|remove)(-all)-tags, bmkp-paste-(add|replace)-tags, bmkp-autofile-(add|remove)-tags:
+;; Swapped order of args MSGP and NO-UPDATE-P (put MSGP last).
+;; bmkp-(add|remove)(-all)-tags, bmkp-autofile-(add|remove)-tags:
+;; Use NO-UPDATE-P also to inhibit display refreshing.
+;; bmkp-remove-tags-from-all: Pass non-nil NO-UPDATE-P arg to bmkp-remove-tags.
+;; 2012/04/07 dadams
+;; Added: bmkp-new-bookmark-default-names (option & function).
+;; Redefine bookmark-make-record (for all Emacs versions) to use bmkp-new-bookmark-default-names.
+;; bookmark-set: Use bmkp-new-bookmark-default-names (multiple defaults).
+;; Moved the region-text default value stuff to fn bmkp-new-bookmark-default-names.
+;; bmkp-completing-read-1: Handle a cons DEFAULT.
+;; Added soft require of thingatpt+.el.
+;; 2012/04/06 dadams
+;; Added: bmkp-auto-idle-bookmark-min-distance, bmkp-not-near-other-auto-idle-bmks,
+;; bmkp-auto-idle-bookmarks.
+;; bmkp-autotemp-bookmark-predicates:
+;; Changed default value to include bmkp-autonamed-bookmark(-this-buffer)-p.
+;; bookmark-store: Add the bookmark to bmkp-auto-idle-bookmarks (if appropriate).
+;; bookmark-delete: Remove the bookmark from bmkp-auto-idle-bookmarks.
+;; bmkp-auto-idle-bookmark-mode:
+;; Bind bmkp-setting-auto-idle-bmk-p. Do nothing if bmkp-not-near-other-auto-idle-bmks says so.
+;; 2012/04/05 dadams
+;; Added (Emacs 21+): bmkp-global-auto-idle-bookmark-mode, bmkp-turn-on-auto-idle-bookmark-mode.
+;; bmkp-auto-idle-bookmark-mode (Emacs 21+):
+;; Made it local:
+;; Removed keyword :global, added keyword :require.
+;; Timer function does nothing if the mode is not enabled (i.e., for the current buffer).
+;; bmkp-auto-idle-bookmark-mode (Emacs 20):
+;; Changed interactive spec to handle toggle symbol.
+;; Timer function does nothing if the mode is not enabled (for the current buffer, if local).
+;; Change message to mention buffer when the mode is local.
+;; Removed: bmkp-auto-idle-bookmark-mode-hook.
+;; Added autoload cookie for Emacs 20 defcustom for bmkp-auto-idle-bookmark-mode.
+;; bmkp-auto-idle-bookmark-mode-timer: Use nil as default value.
+;; bmkp-auto-idle-bookmark-mode: If timer is non-nil, set it to nil (and cancel it).
+;; 2012/04/04 dadams
+;; Added: bmkp-auto-idle-bookmark-mode(-delay|-hook|-lighter|-set-function),
+;; bmkp-temporary-bookmarking-mode-lighter, bmkp-auto-idle-bookmark-mode-timer.
+;; bmkp-temporary-bookmarking-mode: Added lighter.
+;; bookmark-set: Pass INTERACTIVEP arg, not constant MSGP, to bmkp-light-(bookmarks|this-buffer).
+;; 2012/04/03 dadams
+;; Moved to bookmark+-bmu.el: bmkp-face-prop.
+;; 2012/04/02 dadams
+;; bmkp-toggle-autonamed-bookmark-set/delete, bmkp-set-autonamed-bookmark(-at-line),
+;; bmkp-delete-bookmarks:
+;; Made POSITION, NUMBER, ALLP optional.
+;; 2012/03/18 dadams
+;; Added: bmkp-modified-bookmarks, redefinition of bookmark-set-name.
+;; bookmark-store, bookmark-set-name, bookmark-prop-set, bmkp-replace-existing-bookmark:
+;; Add the bookmark to bmkp-modified-bookmarks.
+;; bookmark-rename: Call bmkp-rename-for-marked-and-omitted-lists _after_ set new name w/ prop.
+;; bookmark-save: Reset bmkp-modified-bookmarks. Call bmkp-refresh/rebuild-menu-list.
+;; bmkp-rename-for-marked-and-omitted-lists: Fixed typo: marked -> omitted.
+;; bmkp-edit-bookmark-name-and-file:
+;; Save each of bmk name and file name only if changed (bug fix). Provide default file name.
+;; If no automatic save, and modifications, ask user whether to save.
+;; bmkp-edit-bookmark-records-send:
+;; Add updated bookmarks to bmkp-modified-bookmarks.
+;; Merge sanity-check dolist with main dolist.
+;; Set bmkp-bmenu-marked-bookmarks to names in bmkp-modified-bookmarks, not in edited-bookmarks.
+;; bmkp-edit-bookmark-record: Use (shallow) copy of bmkp-edit-bookmark-orig-record, not original.
+;; bmkp-edit-bookmark-record-send: Add updated bookmark to bmkp-modified-bookmarks.
+;; bmkp-record-visit: Let-bind bmkp-modified-bookmarks to itself, so will be restored.
+;; bmkp-refresh-menu-list: Pass no FILTEREDP if no current filter (start anew).
+;; bmkp-bookmark-name-member: If a name in NAMES is unpropertized, don't try to match property.
+;; bmkp-replace-existing-bookmark: For propertize bookmark-current-bookmark with bmkp-full-record.
+;; 2012/03/13 dadams
+;; bmkp-incremental-filter-delay:
+;; Use bookmark-search-delay as default value, if available. Else use 0.2 (not 0.6).
+;; 2012/03/11 dadams
+;; bmkp-revert-bookmark-file: Added p to interactive spec (forgot).
+;; 2012/03/06 dadams
+;; Added: bmkp-revert-bookmark-file.
+;; bookmark-load: If bookmark-file buffer already existed, do not kill it after loading.
+;; 2012/03/04 dadams
+;; Added: bmkp-refresh/rebuild-menu-list.
+;; bookmark-store, bookmark-send-edited-annotation, bookmark-delete,
+;; bmkp-edit-bookmark-record(s)-send, bmkp-edit-tags-send, bmkp-update-autonamed-bookmark,
+;; bmkp-remove(-all)-tags, bmkp-add-tags, bmkp-file-target-set, bmkp-refresh/rebuild-menu-list:
+;; Use bmkp-refresh/rebuild-menu-list.
+;; bookmark-load:
+;; Use bmkp-refresh/rebuild-menu-list only if interactive. Do not call *-surreptitiously-*.
+;; bmkp-edit-bookmark-record(s)-send: Added optional arg MSGP. Raise read error if batch.
+;; bmkp-record-visit:
+;; Added optional arg BATCHP. Do not bookmark-bmenu-surreptitiously-rebuild-list if BATCHP.
+;; bmkp-edit-tags-send: Added optional arg BATCHP, and pass it to bmkp-record-visit.
+;; bmkp-refresh-menu-list: Use bmkp-bookmark-name-from-record only when BOOKMARK is non-nil.
+;; bmkp-paste-replace-tags, bmkp-(compilation|occur)-target-set-all:
+;; Raise error with OK message if user cancels.
+;; bmkp-purge-notags-autofiles, bmkp-delete-all-temporary-bookmarks: Added optional arg MSGP.
+;; bmkp-purge-notags-autofiles, bmkp-delete-all-temporary-bookmarks,
+;; bmkp-delete-temporary-no-confirm:
+;; Call bmkp-refresh/rebuild-menu-list after the dolist. Inhibit refresh for bookmark-delete.
+;; bmkp-jump-bookmark-file: Removed reference to current-prefix-arg: prompt only if SWITCHP.
+;; bmkp-delete-all-autonamed-for-this-buffer:
+;; Added optional arg MSGP. Prompt for confirmation only if MSGP.
+;; bmkp-delete-autonamed-this-buffer-no-confirm:
+;; Added optional arg NO-REFRESH-P. Inhibit refresh for bookmark-delete.
+;; Unless NO-REFRESH-P, call bmkp-refresh/rebuild-menu-list after the dolist.
+;; bmkp-delete-autonamed-no-confirm:
+;; Call bmkp-delete-autonamed-this-buffer-no-confirm with NO-REFRESH-P.
+;; Call bmkp-refresh/rebuild-menu-list after the dolist.
+;; bmkp-delete-bookmarks:
+;; Added optional arg MSGP. Prompt for confirmation only if MSGP.
+;; Raise error with OK message if user cancels.
+;; Call bmkp-refresh/rebuild-menu-list after the dolist. Inhibit refresh for bookmark-delete.
+;; Use bmkp-this-buffer-alist-only, not bookmark-alist, for selecting bookmarks.
+;; Use `...', etc. when echoing deleted bookmarks.
+;; 2012/03/02 dadams
+;; bookmark-load:
+;; Changed last arg from NO-MSG-P to BATCHP. If non-nil, act with no prompt, saving or not.
+;; If nil, prompt user whether to save before loading. If user quits with C-g, do not load.
+;; bookmark-maybe-load-default-file: Pass symbol nosave, not t, as last arg to bookmark-load.
+;; bmkp-switch-bookmark-file-create: Last arg is now the complement: BATCHP, not INTERACTIVEP.
+;; bmkp-temporary-bookmarking-mode: Pass nosave as last arg to bookmark-load, since do save here.
+;; bmkp-default-handlers-for-file-types: Added eval-when-compile to require cl.el for Emacs 20.
+;; bmkp-maybe-save-bookmarks: Added optional arg SAME-COUNT-P.
+;; bmkp-record-visit: Pass non-nil arg to bmkp-maybe-save-bookmarks to prevent changing mod count.
+;; bookmark-store: Call bmkp-refresh-menu-list if Bookmark List is displayed.
+;; bmkp-toggle-saving-bookmark-file: Added optional arg MSGP - show message only if non-nil.
+;; bmkp-find-file(-other-window): Added missing FIL arg for error format string.
+;; bmkp-temporary-bookmarking-mode: Pass a MSGP arg to bmkp-toggle-saving-bookmark-file.
+;; 2012/02/29 dadams
+;; bmkp-completing-read-lax: Bind & restore C-M-w, C-M-u, SPC, and ? (so can insert SPC, ? etc.).
+;; 2012/02/28 dadams
+;; bmkp-file-target-set: Call bmkp-refresh-menu-list if Bookmark List is displayed.
+;; Renamed option bmkp-default-handler-associations to bmkp-default-handlers-for-file-types.
+;; bmkp-default-handler-associations is NOW OBSOLETE - RENAME IT IF YOU HAVE CUSTOMIZED IT.
+;; bmkp-same-file-p: Take advantage of Emacs 24 function, file-equal-p. Thx to Michael Albinus.
+;; bmkp-find-file(-other-window):
+;; Added optional args CREATE-AUTOFILE-P & MSGP (new arg order). Prefix arg creates bookmark.
+;; Use bmkp-default-handlers-for-file-types even for files not bookmarked.
+;; 2012/02/26 dadams
+;; Added: bmkp-(autofile|autonamed)-history, bmkp-autofile-(all|some)-tags(-regexp)-alist-only,
+;; bmkp-autofile(-(all|some)-tags(-regexp))-jump(-other-window).
+;; bmkp-types-alist: Added entries for (autofile|autonamed).
+;; Everywhere that read-file-name is used:
+;; Bind icicle-unpropertize-completion-result-flag to t, for read-file-name.
+;; No longer alias bmkp-autofile*-jump to bmkp-find-file. The *-autofile-*jump commands use
+;; bmkp-read-bookmark-for-type and bmkp-jump-1, not read-file-name and find-file.
+;; bmkp-find-file(-other-window):
+;; Added optional args FILE MUST-EXIST-P.
+;; Use read-file-name and either bookmark-jump or find-file, not just find-file (and no PRED).
+;; bmkp-find-file-*-tags(-regexp)(-other-window):
+;; Added optional FILE arg.
+;; Use bookmark-jump, not find-file - so only autofiles with the tags are candidates.
+;; Bind icicle-must-pass-after-match-predicate. Use PRED for read-file-name only if no Icicles.
+;; The new bmkp-find-file* commands are bound to ... C-f, not ... a.
+;; bmkp-default-handler-associations: Correct docstring: double backslashes.
+;; 2012/02/21 dadams
+;; bmkp-jump-to-type(-other-window): Corrected ALIST: If no HISTORY do not call *-alist-only.
+;; 2012/02/20 dadams
+;; bookmark-handle-bookmark: Handle, in priority, new property file-handler.
+;; bookmark-default-handler: Handle new property file-handler.
+;; bmkp-make-record-for-target-file:
+;; Use new property file-handler, not handler, for default handler.
+;; Use file-handler with play-sound-file, not handler with bmkp-sound-jump (deprecated).
+;; bmkp-default-handler-for-file: Return function bmkp-user, not a lambda that applies it to file.
+;; bmkp-handler-pred:
+;; Return t if TYPE is handler or file-handler. Do not match a lambda that applies the handler.
+;; bmkp-default-handler-associations, bookmark-alist, bmkp-jump-to-type:
+;; Updated doc string to reflect new implementation of file handlers using prop file-handler.
+;; 2012/02/19 dadams
+;; Added: bmkp-handler-pred, bmkp-temporary-history, bmkp-w32-browser-jump.
+;; bmkp-types-alist: Added bmkp-temporary-history.
+;; bmkp-read-bookmark-for-type: Prepend a space before "bookmark" in prompt.
+;; bmkp-jump-to-type:
+;; Use lax completion.
+;; When call bmkp-read-bookmark-for-type:
+;; Do not append a space to TYPE name passed.
+;; Pass a predicate arg returned by bmkp-handler-pred when TYPE is not a known type.
+;; bmkp-*-jump(-other-window): Remove space after TYPE name passed to bmkp-read-bookmark-for-type.
+;; bmkp-(specific-(buffers|files)|temporary)-jump(-other-window):
+;; Pass specific HIST arg to bmkp-read-bookmark-for-type.
+;; 2012/02/16 dadams
+;; Updated for Emacs 24+:
+;; bookmark-set: Do not set bookmark-(yank-point|current-buffer) if set.
+;; bmkp-make-gnus-record: Be able to bookmark from article buffer, as well as summary buffer.
+;; bmkp-jump-gnus: Go to article buffer if location field says to.
+;; Use bmkp-make-gnus-record (not gnus-summary-bookmark-make-record) for Emacs 24+ also.
+;; 2012/02/14 dadams
+;; bmkp-set-desktop-bookmark: Provide default for read-file-name. Thx to Markus Grunwald.
+;; Provide all bookmarked desktop files as Icicles proxy candidates.
+;; 2012/02/08 dadams
+;; bmkp-autofile-set: Use MSGP also for the case where the bookmark already exists.
+;; bmkp-remove-dups: Redefined to use a hash table.
+;; 2012/02/07 dadams
+;; bmkp-same-file-p: Test compare-strings result using t, not non-nil. Thx to Michael Heerdegen.
+;; 2012/02/04 dadams
+;; Added: bmkp-tags-for-completion, bmkp-tags-in-bookmark-file.
+;; Use bmkp-tags-for-completion for tags completing everywhere - updated doc strings.
+;; bmkp-list-all-tags: Added args current-only-p and (optional) msgp.
+;; Different prefix arg values for different behaviors.
+;; bmkp-tags-list: Added optional arg current-only-p. Use bmkp-tags-for-completion by default.
+;; 2012/01/20 dadams
+;; bmkp(-autofile)-(add|remove)-tags(-from-all), bmkp-find-file-(all|some)-tags(-other-window),
+;; bmkp(-file(-this-dir))-(all|some)-tags-jump(-other-window):
+;; Let user use a prefix arg to refresh tags list. Add this info to doc string.
+;; 2012/01/14 dadams
+;; Corrected bmkp-same-file-p: call to compare-strings.
+;; 2012/01/13 dadams
+;; bmkp-same-file-p: Handle case-sensitivity for local files, at least (not yet done for remote).
+;; 2012/01/08 dadams
+;; Added: bmkp-autonamed-this-buffer-bookmark-p.
+;; bmkp-autotemp-bookmark-predicates: Updated doc string for *-autonamed-this-buffer-bookmark-p.
+;; bmkp-autonamed-bookmark-for-buffer-p: Updated doc string to mention it just checks the name.
+;; bmkp-autonamed-this-buffer-alist-only:
+;; Use bmkp-this-buffer-p, not bmkp-autonamed-bookmark-for-buffer-p.
+;; 2011/12/30 dadams
+;; Renamed bmkp-edit-bookmark to bmkp-edit-bookmark-name-and-file.
+;; Added aliases: bmkp-bookmark-(data|name)-from-record.
+;; Added: bmkp-get-bookmark-in-alist, bmkp-bookmark-record-from-name,
+;; bmkp-edit-bookmark-records-(number|send|mode(-map)),
+;; bookmark-alist-from-buffer (redefinition), bmkp-edit-bookmark-orig-record,
+;; bmkp-rename-for-marked-and-omitted-lists.
+;; Use new names (aliases) bmkp-bookmark-(data|name)-from-record.
+;; bookmark-get-bookmark-record: Use redefinition for all Emacs versions (updated doc string).
+;; bookmark-get-bookmark: Use bmkp-bookmark-record-from-name, with no MEMP check.
+;; bookmark-store: Use bmkp-get-bookmark-in-alist to test whether bookmark exists.
+;; Set the bookmark name also, not just the data, for an existing bookmark.
+;; Unconditionally always put full bookmark on name as property bmkp-full-record.
+;; bookmark-send-edited-annotation, bookmark-rename:
+;; Do bookmark-bmenu-surreptitiously-rebuild-list only if no bmenu display window.
+;; bookmark-rename:
+;; Return OLD if if BATCHP is non-nil and NEW is nil. Do not prompt for name if BATCHP.
+;; Use bmkp-rename-for-marked-and-omitted-lists (rename in those lists too).
+;; Unconditionally always put full bookmark on name as property bmkp-full-record.
+;; Use bmkp-bookmark-record-from-name, not bookmark-get-bookmark, to get full record.
+;; bookmark-delete, bmkp-edit-bookmark-name-and-file, bmkp-edit-bookmark-record,
+;; bmkp-edit-tags(-send), bmkp-toggle-autonamed-bookmark-set/delete:
+;; Use bmkp-get-bookmark-in-alist, not bookmark-get-bookmark.
+;; bookmark-load: Call bmkp-refresh-menu-list only if display is visible, and with NO-MSG-P arg.
+;; bookmark-show-annotation: Do not raise error if not a valid bookmark.
+;; bmkp-edit-bookmark-record: Record bmkp-edit-bookmark-orig-record. Strip properties from name.
+;; Updated edit-buffer text.
+;; bmkp-edit-bookmark-record-send: Rewrote similarly to bmkp-edit-bookmark-records-send. No args.
+;; bmkp-default-bookmark-name:
+;; Use bmkp-bookmark-record-from-name, not bookmark-get-bookmark, requiring membership in ALIST.
+;; bmkp-save-menu-list-state, bmkp-get-tag-value: Added optional arg MSGP, and status messages.
+;; bmkp-make-function-bookmark: Use bmkp-bookmark-record-from-name, not bookmark-get-bookmark.
+;; bmkp-autonamed-bookmark(-for-buffer)-p:
+;; Use bmkp-bookmark-name-from-record, not bookmark-get-bookmark and bookmark-name-from-*.
+;; bmkp-get-tag-value, bmkp-has-tag-p: Removed unused arg MSGP.
+;; bmkp-delete-bookmark-name-from-list:
+;; For unpropertized DELNAME, Set BNAMES to result of delete call.
+;; For propertized DELNAME, delete also unpropertized matches.
+;; bmkp-(compilation|occur)-target-set-all: Do not prompt or show message unless MSGP.
+;; bmkp-describe-bookmark-internals: Use a copy of the bookmark. Strip properties from name.
+;; bmkp-set-autonamed-regexp-buffer: Pass MSGP, do not hardcode.n
+;; Doc string improvements.
+;; 2011/12/24 dadams
+;; bmkp-refresh-menu-list: Added progress message.
+;; bmkp-jump-bookmark-file: Pass NO-MSG-P arg to bookmark-load.
+;; 2011/12/21 dadams
+;; Added: bmkp-orphaned(-local|-remote)-file-(alist-only|bookmark-p),
+;; bmkp-dired-wildcards-bookmark-p.
+;; bookmark-load:
+;; Call (bmkp-refresh-menu-list (bookmark-bmenu-bookmark)), not (bmkp-bmenu-refresh-menu-list).
+;; 2011/12/19 dadams
+;; bookmark-set, bmkp-handle-region-default: Use line-end-position, not end-of-line + point.
+;; 2011/12/17 dadams
+;; bmkp-remote-file-p:
+;; If file-remote-p not available, match /...: (same as ffap-ftp-regexp). Return match.
+;; bmkp-same-file-p: Redefined to use new bmkp-remote-file-p. Thx to M. Heerdegen & M. Albinus.
+;; 2011/12/15 dadams
+;; bmkp-dired-this-dir-bookmark-p: Use file-name-directory, in case filename has wildcards.
+;; 2011/12/13 dadams
+;; bmkp-handle-region-default: Limit buffer-substring-no-properties positions to point-min/max.
+;; 2011/12/06 dadams
+;; bmkp-last-as-first-bookmark-file:
+;; Removed autoload cookie to avoid void-variable error for bookmark-default-file.
+;; bmkp-edit-bookmark, bookmark-rename: Use bmkp-completing-read-lax, not read-from-minibuffer.
+;; 2011/12/05 dadams
+;; bmkp-this-buffer-p:
+;; Do not use buffer-file-name (for Dired). Wrap bookmark-buffer-file-name with condition-case.
+;; bookmark-save: Swap write order, so last message is about the bookmark file, not customize.
+;; 2011/12/03 dadams
+;; Renamed: bmkp-use-bookmark-file-create to bmkp-switch-bookmark-file-create.
+;; Added: bmkp-last-as-first-bookmark-file, bookmark-maybe-load-default-file (redefinition),
+;; bookmarks-already-loaded (redefinition), bmkp-default-bookmark-file.
+;; bookmark-save: Update and save bmkp-last-as-first-bookmark-file.
+;; bookmark-load: New default for reading file name, and require an existing file (match).
+;; Update and save bmkp-last-as-first-bookmark-file. Update bmkp-sorted-alist.
+;; bmkp-switch-bookmark-file (no longer used): New default for reading file name.
+;; bmkp-switch-bookmark-file-create: Added optional arg INTERACTIVEP. New default for reading
+;; file name. Use bookmark-load, not bmkp-switch-bookmark-file. Require confirmation only for
+;; new, empty file. Added final message.
+;; bmkp-switch-to-last-bookmark-file: Use bmkp-last-as-first-bookmark-file as first fallback.
+;; bmkp-set-bookmark-file-bookmark: Use bmkp-read-bookmark-file-name, not read-file-name.
+;; New default for reading file name.
+;; bmkp-temporary-bookmarking-mode: Use bookmark-load, not bmkp-switch-bookmark-file.
+;; Removed: bookmark-maybe-message. Use only message now, not bookmark-maybe-message.
+;; bmkp-autofile-set: For Emacs 23.3+, provide multiple defaults for file name.
+;; 2011/11/30 dadams
+;; bmkp-same-file-p: Avoid having Tramp prompt for passwords, when possible. Thx to M. Heerdegen.
+;; bmkp-toggle-autotemp-on-set: Removed ARG (copy/paste typos).
+;; 2011/11/28 dadams
+;; bmkp-set-bookmark-file-bookmark: Prompt user for bookmark name here, to make clear what it is.
+;; 2011/11/27 dadams
+;; bookmark-write-file: If write error, do not overwrite message. And show error msg for 4 sec.
+;; 2011/11/18 dadams
+;; Renamed: bmkp-bookmark-image-bookmark-p to bmkp-image-bookmark-p.
+;; Added: bmkp-image-alist-only, bmkp-image-jump(-other-window), bmkp-image-history.
+;; bookmark-handle-bookmark: If bmk has handler but it's not a function, use default handler.
+;; bmkp-autotemp-bookmark-predicates: Update doc string to include bmkp-image-bookmark-p.
+;; bmkp-types-alist: Added entry for images.
+;; 2011/11/15 dadams
+;; bookmark-relocate: Redefine without using old-*. Update Dired location too.
+;; Added: bmkp-cycle-this-file(/buffer)(-other-window),
+;; bmkp-(next|previous)-bookmark-this-file(/buffer)(-repeat),
+;; bmkp-this-file(/buffer)-bmenu-list, bmkp-this-file/buffer-alist-only.
+;; Renamed bmkp-this-buffer-cycle-sort-comparer to bmkp-this-file/buffer-cycle-sort-comparer.
+;; bmkp-this-buffer-p: Return nil if bookmark has a file diff from buffer.
+;; bmkp-this-file-p:
+;; Ensure bmkp-file-bookmark-p and bookmark-buffer-file-name. Use bmkp-same-file-p.
+;; 2011/11/09 dadams
+;; bmkp-jump-dired, bmkp-jump-man: Added bmkp-select-buffer-other-window to other-window fns.
+;; 2011/11/08 dadams
+;; bmkp-edit-bookmark: For new file name, use read-file-name, not read-from-minibuffer.
+;; 2011/11/03 dadams
+;; Renamed: bmkp-autoname-bookmark to bmkp-autoname-bookmark-function-default.
+;; 2011/11/01 dadams
+;; Added: bmkp-temporary-jump(-other-window).
+;; bmkp-bookmark-description: Title now indicates whether temporary.
+;; 2011/10/31 dadams
+;; Added: bmkp-toggle-autotemp-on-set, bmkp-autotemp-all-when-set-p.
+;; bookmark-set: If bmkp-autotemp-all-when-set-p call bmkp-make-bookmark-temporary.
+;; 2011/10/28 dadams
+;; Added: bmkp-delete-temporary-no-confirm.
+;; bmkp-delete-all-temporary-bookmarks: Rewrote (it was just a stub).
+;; bmkp-bmenu-menubar-menu:
+;; Added: bmkp-temporary-bookmarking-mode, bmkp-delete-all-temporary-bookmarks,
+;; bmkp-bmenu-toggle-marked-temporary/savable.
+;; bmkp-bmenu-show-menu: Added: bmkp-bmenu-show-only-temporary.
+;; bmkp-bmenu-mark-menu:
+;; Added: bmkp-bmenu-mark-temporary-bookmarks, bmkp-bmenu-mark-autonamed-bookmarks.
+;; bmkp-bmenu-mouse-3-menu: Added: bmkp-bmenu-toggle-temporary.
+;; bookmark-bmenu-mode: Updated doc string.
+;; 2011/10/27 dadams
+;; Added: bmkp-autotemp-bookmark-predicates, bmkp-temporary-bookmarking-mode(-hook),
+;; bmkp-delete-all-temporary-bookmarks, bmkp-make-bookmark-(savable|temporary),
+;; bmkp-toggle-temporary-bookmark, bmkp-temporary-alist-only, bmkp-temporary-bookmark-p.
+;; bookmark-set: Make bookmark temporary, if bmkp-autotemp-bookmark-predicates says to.
+;; bookmark-write-file: Do not save temporary bookmarks (bmkp-temporary-bookmark-p).
+;; 2011/10/25 dadams
+;; bmkp-empty-file: Added optional arg CONFIRMP. By default, no confirmation if not interactive.
+;; 2011/08/09 dadams
+;; Bind icicle-unpropertize-completion-result-flag to t for all calls to completing-read.
+;; 2011/08/07 dadams
+;; Added: bmkp-guess-default-handler-for-file-flag, bmkp-file-bookmark-handlers.
+;; bmkp-file-bookmark-p: Use bmkp-file-bookmark-handlers, which means also image-bookmark-jump.
+;; bmkp-make-record-for-target-file (need to keep in sync with diredp-bookmark):
+;; Instead of image-bookmark-make-record, use explicit function that includes file and type.
+;; bmkp-default-handler-for-file:
+;; Use bmkp-guess-default only if bmkp-guess-default-handler-for-file-flag is non-nil.
+;; bmkp-default-handler-associations: Updated doc string.
+;; 2011/08/05 dadams
+;; bmkp-file-bookmark-p: Allow handler to be bmkp-default-handler-for-file, e.g. for image files.
+;; bmkp-all-tags-alist-only: Corrected.
+;; bmkp-refresh-menu-list: Ensure BOOKMARK is a string.
+;; bmkp-every: Removed unused binding.
+;; 2011/05/08 dadams
+;; Just put some definitions in alphabetic order - no real change.
+;; 2011/04/25 dadams
+;; bmkp-bookmark-description: Added optional arg NO-IMAGE.
+;; bmkp-url-target-set: Protect url-get-url-at-point with fboundp.
+;; bmkp-(file-target|autofile)-set, bmkp-autofile-(add|remove)-tags:
+;; Added buffer-file-name as a default possibility. Removed URL functions for that purpose.
+;; 2011/04/24 dadams
+;; Added: bmkp-purge-notags-autofiles.
+;; bookmark-delete: Redefined to accept either bookmark or name as arg.
+;; bmkp-(url|file|compilation|occur)-target-set(-all), bmkp-autofile-(set|(add|remove)-tags):
+;; Removed optional args when read prefix.
+;; bmkp-occur-target-set-all: Made PREFIX arg optional too.
+;; Added some missing autoload cookies. Removed some from non-def sexps.
+;; 2011/04/21 dadams
+;; Added: bmkp-copied-tags, bmkp-copy-tags, bmkp-paste-add-tags, bmkp-paste-replace-tags..
+;; 2011/04/20 dadams
+;; bmkp-remove-all-tags: Added optional arg no-cache-update-p.
+;; 2011/04/19 dadams
+;; bmkp-make-record-for-target-file: Fixed backquotes on lambdas.
+;; 2011/04/17 dadams
+;; bmkp-edit-tags: Do not apply bmkp-full-tag to the tags.
+;; 2011/04/16 dadams
+;; Added: bmkp-edit-tags(-send|-mode(-map)), bmkp-return-buffer.
+;; bookmark-(rename|relocate|send-edited-annotation), bmkp-update-autonamed-bookmark,
+;; bmkp-(add|remove(-all)-tags:
+;; Wrap with-current-buffer around bmkp-refresh-menu-list.
+;; bookmark-(store|rename|write-file): Test emacs-major-version, not just (boundp 'print-circle).
+;; bmkp-autofile-add-tags: Fix interactive args - forgot to include DIR arg (= nil).
+;; 2011/04/15 dadams
+;; Added: bmkp-autofile-alist-only, bmkp-autofile-bookmark-p.
+;; 2011/04/13 dadams
+;; Added: bmkp-autofile-jump(-other-window) (aliases), bmkp-find-file(-other-window).
+;; bmkp-find-file-(all|some)-tags(-regexp)(-other-window): Bind use-file-dialog to nil.
+;; 2011/04/12
+;; Added: bmkp-bookmark-name-member, bmkp-names-same-bookmark-p, bmkp-sort-omit,
+;; bmkp-remove-omitted, bmkp-delete-bookmark-name-from-list, bmkp-bookmark-a-file (alias),
+;; bmkp-autofile-(add|remove)-tags, bmkp-(un)tag-a-file (aliases),
+;; bmkp-get-autofile-bookmark, bmkp-find-file-(all|some)-tags(-regexp)(-other-window).
+;; Removed: bmkp-remove-assoc-dups, bmkp-sort-and-remove-dups.
+;; Applied renaming: bmkp-bmenu-omitted-list to bmkp-bmenu-omitted-bookmarks.
+;; bookmark-store: Redefine for all Emacs versions now:
+;; Put the bookmark on the name as property bmkp-full-record. Use bmkp-maybe-save-bookmarks.
+;; Return the bookmark.
+;; bookmark-get-bookmark: Redefine for all Emacs versions now:
+;; If BOOKMARK is a bookmark-name string that has property bmkp-full-record, return that value.
+;; bookmark-send-edited-annotation: Make sure it's the annotation buffer that gets killed.
+;; bookmark-default-handler: Return nil, like vanilla (but why?).
+;; bookmark-location: Pass full bookmark to the various "get" functions.
+;; bookmark-rename: Put bmkp-full-record property on new name.
+;; bookmark-delete:
+;; Use bmkp-delete-bookmark-name-from-list: If name has bmkp-full-record property, use that
+;; with name to find bookmark to delete.
+;; Pass full bookmark to unlight.
+;; bmkp-edit-bookmark: Save if either is non-empty, not if both are. Thx to Michael Heerdegen.
+;; bmkp-edit-bookmark-record: Bind print-circle to t around pp.
+;; bmkp-default-bookmark-name:
+;; Use bookmark-name-from-full-record plus bookmark-get-bookmark, not assoc.
+;; If BNAME is nil (no default) then do not try to look it up in alist.
+;; bookmark-write-file: Unpropertize only for Emacs 20 or nil bmkp-propertize-bookmark-names-flag.
+;; Bind print-circle to t around pp.
+;; bmkp-save-menu-list-state: Make it interactive (a command). Bind print-circle.
+;; Use bmkp-maybe-unpropertize-bookmark-names on alists and name lists.
+;; Bind print-circle to t around pp.
+;; bmkp-unomit-all: Use bmkp-delete-bookmark-name-from-list, not delete.
+;; bmkp-dired-this-dir-bookmark-p: Use bmkp-same-file-p, not string=.
+;; bmkp-url-target-set, bmkp-replace-existing-bookmark:: Return the bookmark.
+;; bmkp-file-target-set: Return bookmark. Added arg MSGP: msg if no file yet.
+;; bmkp-autofile-set:
+;; Added DIR arg and MSGP arg: msg if no file yet. Return the bookmark.
+;; If read absolute file name, create bmk in its dir, not in default-directory. Else use DIR.
+;; Use bmkp-get-autofile-bookmark, so uses bmkp-same-file-p for each file part (not equal).
+;; bmkp-marked-bookmark-p, bmkp-omitted-bookmark-p: Use bmkp-bookmark-name-member, not member.
+;; bookmark-location: Pass full bookmark to the various "get" functions.
+;; bmkp-choose-navlist-from-bookmark-list, bmkp-cycle-this-buffer:
+;; Use bmkp-sort-omit, not bmkp-sort-and-remove-dups.
+;; bmkp-bookmark-description, bmkp-describe-bookmark-internals: Add Bookmark `' to title.
+;; bmkp-make-bookmark-list-record: Use bmkp-maybe-unpropertize-bookmark-names on lists.
+;; bmkp-printable-p: Bind print-circle to t around prin1.
+;; bmkp-delete-autonamed(-this-buffer)-no-confirm:
+;; Do nothing if bookmarks not loaded. Thx to Christoph Scholtes.
+;; 2011/04/03 dadams
+;; Added: bmkp-make-record-for-target-file, bmkp-replace-existing-bookmark (not used).
+;; bmkp-file-this-dir-bookmark-p: Corrected it to compare directory to default-directory.
+;; bmkp-file-target-set: Added arg NO-OVERWRITE (pass to bookmark-store).
+;; Use (new) bmkp-make-record-for-target-file.
+;; bmkp-autofile-set: Do nothing if bookmark with same name, file and dir exists.
+;; Else create one, even if the bookmark name is the same.
+;; You can have multiple autofile bookmarks with the same name (diff files).
+;; 2011/04/02 dadams
+;; Added: bmkp-autofile-set, bmkp-file-this-dir-(all|some)-tags(-regexp)-jump(-other-window),
+;; bmkp-file-this-dir-(all|some)-tags(-regexp)-alist-only.
+;; 2011/04/01 dadams
+;; Moved key and menu bindings to (new) bookmark+-key.el.
+;; Added: bmkp-(dired|file)-this-dir-alist-only, bmkp-(dired|file)-this-dir-bookmark-p,
+;; bmkp-file-this-dir-jump(-other-window).
+;; Renamed: bmkp-dired-jump-current(*) to bmkp-dired-this-dir-jump(*).
+;; bmkp-dired-this-dir-jump(-other-window): Use bmkp-dired-this-dir-alist-only.
+;; bmkp-types-alist: Added (dired|file)-this-dir.
+;; Bound bmkp-(dired|file)-this-dir-jump to C-d and C-f in bookmark-jump(-other-window)-map.
+;; bmkp-jump-dired, bmkp-jump-man: Treat null bmkp-jump-display-function as display-buffer.
+;; 2011/03/26 dadams
+;; Added: bmkp-file-(all|some)-tags(-regexp)-(alist-only|jump(-other-window)).
+;; bmkp-jump-menu: Added the new commands, but not Emacs 20, to avoid crash if byte-compiled.
+;; bmkp-bookmark-jump*-other-window: Simplified doc strings - refer to same-window version.
+;; 2011/03/17 dadams
+;; bmkp-describe-bookmark: Added 10-pixel margin around thumbnail image.
+;; 2011/03/11 dadams
+;; Protect use of mouse-wheel-*-event with boundp. Thx to Chris Poole.
+;; 2011/03/04 dadams
+;; bmkp-bookmark-description, bmkp-describe-bookmark: Added clickable thumbnail to the help.
+;; bmkp-bookmark-description: Split file name into dir & relname, so shorter line, in help.
+;; 2011/03/03 dadams
+;; Added: bmkp-all-exif-data, bmkp-bookmark-image-bookmark-p.
+;; bmkp-bookmark-description: Handle image EXIF data.
+;; 2011/01/03 dadams
+;; Removed autoload cookies from non def* sexps and from define-key and define-prefix-command.
+;; Added some missing autoload cookies for commands, in particular redefined standard commands.
+;; 2010/12/10 dadams
+;; Added defalias for bookmark-name-from(-full)-record, to fix gratuitous Emacs name change.
+;; 2010/10/22 dadams
+;; Uncommented key bindings for mouse wheel, since Emacs bug #6256 has now been fixed.
+;; bmkp-repeat-command: Don't bother to let-bind repeat-previous-repeated-command,
+;; and use setq, not let, for last-repeatable-command. Thx to Stefan Monnier.
+;; 2010/09/28 dadams
+;; Added: bmkp-delete-autonamed(-this-buffer)-no-confirm.
+;; 2010/09/25 dadams
+;; Added: option bmkp-default-bookmark-name, bmkp-annotated-alist-only.
+;; Added: bmkp-(next|previous)-*(-repeat), using macro bmkp-define-next+prev-cycle-commands.
+;; bmkp-default-bookmark-name: Respect option.
+;; bookmark-edit-annotation-mode, bookmark-edit-annotation:
+;; Use bmkp-annotated-alist-only (and new bmkp-default-bookmark-name).
+;; bookmark-send-edited-annotation:
+;; End in orig buffer, not bmenu buffer. Delete edit window. Thx to Joe Bloggs.
+;; 2010/09/24 dadams
+;; Added: bmkp-autonamed(-this-buffer)-jump(-other-window). Bound to C-x j # (#|.) and menus.
+;; Added, using bmkp-define-cycle-command:
+;; bmkp-cycle-(autonamed|bookmark-list|desktop|dired|gnus|info|lighted|(local-|remote-)file|
+;; man|non-file|remote-file|specific-(buffers|files)|variable-list|url)
+;; (-other-window).
+;; Added redefinitions: bookmark-edit-annotation(-mode).
+;; Renamed: *varlist* to *variable-list*.
+;; bmkp-autoname-format: Added ^ to anchor numeral at beginning.
+;; bookmark--jump-via: Don't update autonamed if using w32 association.
+;; bmkp-update-autonamed-bookmark: bmkp-refresh-menu-list only if buffer list is displayed.
+;; *-(relocate|rename), *-update-autonamed-bookmark, *-remove-all-tags, *-(add|remove)-tags:
+;; Don't create bookmark-list buffer if doesn't exist.
+;; bookmark-show-(annotation|all-annotations): Restore selected window and frame focus.
+;; bmkp-completing-read-(buffer|file)-name: Added optional NO-DEFAULT-P arg.
+;; bmkp-describe-bookmark: Default to highlighted bookmarks on line, if there are any.
+;; bmkp-specific-(buffers|files)-jump(-other-window): Allow empty input, to end loop.
+;; bmkp-cycle: Ensure bmkp-current-nav-bookmark is a bookmark, else redefine. Use %9d, not %d.
+;; bmkp-cycle-other-window: Added optional STARTOVERP arg here too.
+;; 2010/09/20 dadams
+;; bmkp-choose-navlist-of-type: Empty input means "any".
+;; 2010/09/16 dadams
+;; bmkp-read-bookmark-file-name:
+;; Removed extra default-filename in call to read-file-name. Thx to Pedro Insua.
+;; 2010/08/22 dadams
+;; Added: bmkp-regexp-filtered-annotation-alist-only.
+;; 2010/08/20 dadams
+;; Added: bmkp-read-bookmark-file-name.
+;; bookmark-save, bookmark-load, bmkp-switch-bookmark-file, bmkp-use-bookmark-file-create:
+;; Use bmkp-read-bookmark-file-name.
+;; 2010/08/19 dadams
+;; Require gnus-sum.el when compile (for macro). Thx to S. Nemec.
+;; 2010/08/18 dadams
+;; Removed eval-when-compile for bookmark+-lit.el.
+;; Replaced defvar of bmkp-edit-bookmark-record-mode-map with a define-key after derived mode.
+;; 2010/08/17 dadams
+;; bmkp-edit-bookmark: Made interactive. Bound to C-x p E. Added optional INTERNALP arg.
+;; bmkp-info-bookmark-p: Return nil if a different handler.
+;; 2010/08/15 dadams
+;; Moved bmkp-define-file-sort-predicate, bmkp-menu-bar-make-toggle to bookmark+-mac.el.
+;; Require: bookmark.el, bookmark+-mac.el.
+;; Require for compile: bookmark+-bmu.el, bookmark+-lit.el (soft).
+;; Ensure this file is loaded before compiling.
+;; bmkp-set-bookmark-file-bookmark: Added missing arg for error format string.
+;; 2010/08/08 dadams
+;; bookmark-jump: Added optional arg DISPLAY-FUNCTION (Emacs 24).
+;; bookmark-handle-bookmark:
+;; Move non-default handler call outside condition-case.
+;; Updated for Emacs 24: Use error condition bookmark-error-no-filename. Added props for it.
+;; bookmark-default-handler: Updated for Emacs 24:
+;; Signal condition bookmark-error-no-filename, not file-error, and pass (stringp FILE).
+;; bookmark-make-record-default: Added optional args NO-CONTEXT, POSITION (Emacs 24), and VISITS.
+;; bookmark-load: Updated for Emacs 24: Wrap with abbreviate-file-name.
+;; bmkp-jump-1: Allow arg to be a bookmark or its name.
+;; bmkp-gnus-bookmark-p: Updated for Emacs 24: Added gnus-summary-bookmark-jump.
+;; bmkp-jump-gnus: Different gnus-fetch-group call for Emacs 20, 21.
+;; bmkp-make-(desktop|varlist|bookmark-(file|list))-record: Call *-record-default with NO-CONTEXT.
+;; w3m-current-title: Use w3m-current-title as bookmark name.
+;; bmkp-w3m-set-new-buffer-name, bmkp-jump-w3m*: Require w3m.
+;; bmkp-make-gnus-record: Get bookmark name from gnus-summary-article-header.
+;; Update for Emacs 24: Bypass bmkp specific Gnus, man, and woman code.
+;; 2010/08/06 dadams
+;; Added (and bound the commands):
+;; bmkp-(compilation|occur)-target-set(-all), bmkp-(file|url)-target-set,
+;; bmkp-default-handler-associations, bmkp-compilation-file+line-at,
+;; bmkp-default-handler-(for-file|user), bmkp-sound-jump.
+;; bmkp-occur-create-autonamed-bookmarks: Do not define it for Emacs < 22. Protect wrt POS, BUF.
+;; Added to Bookmark menu: bmkp-(file|url)-target-set, bmkp-set-(bookmark-file|desktop)-bookmark.
+;; 2010/08/04 dadams
+;; bmkp-edit-bookmark: Use new bookmark name for update of dired-directory. Thx to Kai Tetzlaff.
+;; 2010/08/03 dadams
+;; bmkp-make-url-browse-record: Remove text properties from URL arg.
+;; 2010/07/17 dadams
+;; Added: bmkp-url-jump-(other-window), bmkp-url(-browse)-(alist-only|bookmark-p), bmkp-url-cp,
+;; bmkp-url-history, bmkp-make-url-browse-record, bmkp-jump-url-browse.
+;; bmkp-sort-comparer: Use bmkp-url-cp, not bmkp-w3m-cp.
+;; bmkp-types-alist: w3m -> url.
+;; bookmark-alist: Updated doc string to mention LOCATION. W3M -> URL.
+;; bmkp-bookmark-description: Treat URL. Set no-position-p depending on start.
+;; Bind bmkp-url-jump*. Replace W3M by URL in menu items.
+;; 2010/07/14 dadams
+;; Created from bookmark+.el code.
+
+;;;(@* "CHANGE LOG FOR `bookmark+-bmu.el'")
+;;
+;; 2022/01/14 dadams
+;; bmkp-bmenu-edit-marked: Enable undo inside with-current-buffer (not significant).
+;; 2021/09/19 dadams
+;; Moved defgroup from here to bookmark+.el, for new defcustom bmkp-bmenu-buffer.
+;; Everywhere: Use bmkp-bmenu-buffer, not vanilla bookmark-bmenu-buffer.
+;; bmkp-bmenu-barf-if-not-in-menu-list: Test mode with derived-mode-p; don't test buffer name.
+;; 2021/08/18 dadams
+;; Applied renaming of bmkp-auto-idle-bookmark-mode to bmkp-automatic-bookmark-mode.
+;; 2021/04/16 dadams
+;; bookmark-bmenu-execute-deletions:
+;; Use bmkp-get-bookmark, not bookmark-get-bookmark, but in vanilla-compatible way.
+;; bmkp-bmenu-make-sequence-from-marked, bmkp-bmenu-remove-tags-from-marked,
+;; bmkp-bmenu-propertize-item, bmkp-bmenu-marked-or-this-or-all:
+;; Use bmkp-get-bookmark, not bookmark-get-bookmark.
+;; 2021/03/05 dadams
+;; Face bmkp-no-local: changed default to orange background, from yellow foreground.
+;; 2021/03/04 dadams
+;; bmkp-bmenu-describe-marked: Typo - bmkp-describe-bookmark-marked -> bmkp-bmenu-describe-marked.
+;; 2020/12/29 dadams
+;; Wrap soft-require of menu-bar+.el in null condition-case, because it soft-requires Bookmark+.
+;; 2020/11/27 dadams
+;; bmkp-bmenu-define-command, bmkp-bmenu-define-full-snapshot-command:
+;; Use copy-sequence for lists, because some code modifies the list structure.
+;; If command already defined then prompt to overwrite its definition (replace all existing).
+;; bmkp-bmenu-define-full-snapshot-command:
+;; Bind bookmark-alist to non-nil bmkp-latest-bookmark-alist. NB: Contradicts 2015-02-22 change.
+;; 2020/11/26 dadams
+;; bmkp-bmenu-read-filter-input:
+;; Set, don't bind, bmkp-bmenu-filter-(title|function). Restore them and the pattern, if C-g.
+;; 2020/11/06 dadams
+;; bmkp-bmenu-read-filter-input:
+;; Bind prefix-command-echo-keystrokes-functions to nil. See Emacs bug #44500.
+;; 2020/07/04 dadams
+;; Changed all references to `C-x p' to `C-x x'.
+;; Replaced string *Bookmark List* with bookmark-bmenu-buffer (for Emacs 28).
+;; 2020/01/26 dadams
+;; Added: bmkp-bmenu-sort-annotated-before-unannotated (bound to s a).
+;; 2020/01/22 dadams
+;; bookmark-bmenu-list: Restore bookmark-bmenu-list to saved value, last-previous-bookmark-file.
+;; bookmark-bmenu-mode: Added to doc: *-(switch-to-bookmark-file|save-bookmarks)-this-file/buffer.
+;; bmkp-bmenu-bookmark-file-menu: Added bmkp-switch(-to-last)-bookmark-file(-create). Reordered.
+;; 2020/01/15 dadams
+;; Added: bmkp-bmenu-edit-annotations-for-marked.
+;; Bind bookmark-bmenu-(show|edit)-annotation, bookmark-bmenu-show-all-annotations,
+;; bmkp-bmenu-edit-annotations-for-marked to new prefix key a (a, e, A, >) and in
+;; bmkp-bmenu-(edit|show)-menu and bmkp-bmenu-mouse-3-menu.
+;; No longer bind bmkp-bmenu-show-or-edit-annotation.
+;; 2019/10/29 dadams
+;; bookmark-bmenu-relocate: Ensure that arg to bookmark-relocate is not nil.
+;; bookmark-bmenu-bookmark: Mention in doc: nil return if no bookmark.
+;; bookmark-bmenu-show-annotation, bmkp-bmenu-w32-open-with-mouse: Raise error if no bookmark.
+;; bmkp-bmenu-show-menu: Enable bookmark-bmenu-show-annotation only if there is a bookmark.
+;; 2019/08/13 dadams
+;; Added bmkp-bmenu-clone-bookmark, bmkp-bmenu-copy-bookmark (alias). Bound to M-n in bmk list.
+;; Added it to bmkp-bmenu-menubar-menu, bmkp-bmenu-mouse-3-menu.
+;; 2019/08/09 dadams
+;; bmkp-file-handler: Changed default to LightBlue background.
+;; 2019/05/19 dadams
+;; Bind print-gensym wherever we bind print-circle.
+;; 2019/04/23 dadams
+;; Added bmkp-bmenu-edit-menu.
+;; Moved bmkp-bmenu-edit-marked to bmkp-bmenu-edit-menu from main Bookmark+ menu.
+;; bmkp-bmenu-show-menu: Added bookmark-bmenu-show-annotation.
+;; 2018/11/24 dadams
+;; bookmark-bmenu-other-(window|frame):
+;; Added missing bookmark-name arg to b-j-o-(window|frame). Thx to Alan Wehmann.
+;; Added: bmkp-bmenu-load-marking, bmkp-bmenu-load-marking-unmark-first.
+;; bmkp-bmenu-(bookmark-file|mark)-menu: Added bmkp-bmenu-load-marking(-unmark-first).
+;; 2018/10/10 dadams
+;; Added: bookmark-bmenu-other-frame.
+;; bookmark-bmenu-mode: Added bookmark-bmenu-other-frame to doc string.
+;; 2018/09/21 dadams
+;; Added: bmkp--pop-to-buffer-same-window. (Added also to bookmark+-lit.el.)
+;; bookmark-bmenu-2-window, bookmark-bmenu-this-window:
+;; Use bmkp--pop-to-buffer-same-window, not switch-to-buffer.
+;; 2018/08/28 dadams
+;; bmkp-bmenu-read-filter-input: Do not pass non-characterp value to text-char-description.
+;; 2017/10/27 dadams
+;; bookmark-bmenu-mode: Added to doc string: bmkp-bmenu-paste-(add|replace)-tags.
+;; 2017/10/14 dadams
+;; All EWW stuff is for Emacs 25+, not Emacs 24.4+.
+;; 2017/10/08 dadams
+;; bmkp-bmenu-describe-marked: Bind print-(circle|length|level) so pp-to-string prints all.
+;; 2017/07/03 dadams
+;; Added: bmkp-bmenu-sort-by-Info-position.
+;; Renamed bmkp-bmenu-sort-by-Info-location to bmkp-bmenu-sort-by-Info-node-name.
+;; bookmark-bmenu-mode: Updated doc string for Info-bookmark sorting.
+;; bmkp-bmenu-sort-by-bookmark-type, bmkp-bmenu-sort-by-Info-node-name:
+;; Applied renaming of bmkp-info-cp to bmkp-info-node-name-cp.
+;; Bind bmkp-bmenu-sort-by-Info-position to s I.
+;; bmkp-bmenu-sort-menu:
+;; Added bmkp-bmenu-sort-by-Info-position. Renamed By Info Node to By Info Node Name.
+;; 2017/03/30 dadams
+;; bmkp-bmenu-mark-*-bookmarks:
+;; Added optional arg MSGP. Pass it to bmkp-bmenu-mark-bookmarks-satisfying.
+;; bmkp-bmenu-mark-(orphaned-local-)file-bookmarks: Made argument ARG optional.
+;; bmkp-bmenu-mark-bookmarks-satisfying: Added missing \ni to interactive spec.
+;; 2017/01/10 dadams
+;; Renamed bmkp-toggle-allow-multi-tabs-for-w3m to bmkp-toggle-w3m-allow-multiple-buffers.
+;; bmkp-bmenu-toggle-menu: Added bmkp-toggle-eww-allow-multiple-buffers.
+;; 2017/01/08 dadams
+;; Use the term "entry", not "property" everywhere, for bookmark entries (fields).
+;; 2017/01/07 dadams
+;; bmkp-bmenu-copy-marked-to-bookmark-file: Use bookmark-file-coding-system (Emacs bug #25365).
+;; 2017/01/02 dadams
+;; bmkp-bmenu-mouse-3-menu: Added menu item Store Org Link.
+;; 2016/12/31 dadams
+;; Added: bmkp-bmenu-mark-non-invokable-bookmarks, bmkp-bmenu-show-only-non-invokable-bookmarks.
+;; Bound them to nM and nS. Added them to menus bmkp-bmenu-(mark|show)-types-menu.
+;; bookmark-bmenu-mode: Include non-invokable bookmarks in doc string.
+;; bmkp-bmenu-propertize-item: Handle non-invokable bookmarks.
+;; 2016/11/23 dadams
+;; bookmark-bmenu-mode: Doc string cleanup.
+;; bookmark-bmenu-list, bmkp-bmenu-copy-marked-to-bookmark-file:
+;; Raise an error if we have a directory, not a file.
+;; bmkp-bmenu-create-bookmark-file-from-marked: Ensure that FILE is not a directory.
+;; 2016/11/18 dadams
+;; Support Emacs 24.[45] too.
+;; 2016/11/15 dadams
+;; bmkp-*eww-*: Ensure that EWW code is only for Emacs 25+.
+;; 2016/11/14 dadams
+;; Added: bmkp-bmenu-mark-eww-bookmarks, bmkp-bmenu-show-only-eww-bookmarks.
+;; bookmark-bmenu-mode: Added EWW to doc.
+;; Bound bmkp-bmenu-mark-eww-bookmarks to WEM, bmkp-bmenu-show-only-eww-bookmarks to WES.
+;; Change bmkp-bmenu-mark-w3m-bookmarks to W3M, bmkp-bmenu-show-only-w3m-bookmarks binding to W3S.
+;; bmkp-bmenu-mark-types-menu, bmkp-bmenu-show-types-menu: Support EWW.
+;; 2016/06/24 dadams
+;; bookmark-bmenu-execute-deletions: Delete bookmark on the current line if none flagged/marked.
+;; 2016/06/23 dadams
+;; bmkp-bmenu-(add|remove)-tags-(to|from)-marked, bmkp-bmenu-paste-(add|replace)-tags-for-marked:
+;; Call bmkp-maybe-save-bookmarks (after the iteration). Thx to Alan Wehmann.
+;; 2016/06/21 dadams
+;; bmkp-bmenu-add-tags-to-marked, bmkp-bmenu-remove-tags-from-marked,
+;; bmkp-bmenu-paste-(add|replace)-tags-to-marked:
+;; Put bookmark-save-flag let-binding around iteration only, so modification is recorded etc.
+;; 2016/06/11 dadams
+;; bmkp-bmenu-list-1, bookmark-bmenu-hide-filenames:
+;; Use string-width, not length. Thx to Toshikazu Nakamura.
+;; 2015/11/07 dadams
+;; bmkp-bmenu-copy-marked-to-bookmark-file: Added missing zerop test for No-changes case.
+;; bmkp-bmenu-create-bookmark-file-from-marked:
+;; Added missing MOVEP arg in call to bmkp-bmenu-copy-marked-to-bookmark-file.
+;; 2015/11/02 dadams
+;; bmkp-bmenu-copy-marked-to-bookmark-file:
+;; If modified, prompt to save bookmark file copied from, before copying.
+;; For copy (not move): reload the original bookmark file, then refresh display from it.
+;; 2015/10/31 dadams
+;; bmkp-bmenu-move-marked-to-bookmark-file:
+;; Just call bmkp-bmenu-copy-marked-to-bookmark-file. It now deletes moved and refreshes list.
+;; bmkp-bmenu-copy-marked-to-bookmark-file:
+;; Added arg MOVEP. If move, delete before refresh list (deletes bmks returned in IMPORTED).
+;; 2015/06/26 dadams
+;; Added: bmkp-bmenu-mark-function-bookmarks, bmkp-bmenu-show-only-function-bookmarks.
+;; Bound the to Q M and Q S. Added to bmkp-bmenu-show-types-menu.
+;; bookmark-bmenu-mode: Updated the doc string for them.
+;; bmkp-bmenu-show-only(-orphaned-local)-file-bookmarks: Made ARG optional.
+;; 2015/05/15 dadams
+;; Fixed typo: bmkp-bmenu-show-only-lighted -> bmkp-bmenu-show-only-lighted-bookmarks everywhere.
+;; 2015/04/15 dadams
+;; bmkp-bmenu-describe-this-bookmark: save-selected-frame -> save-selected-window.
+;; 2015/03/20 dadams
+;; Added: bmkp-bmenu-show-this-annotation+move-down, bmkp-bmenu-show-this-annotation+move-up,
+;; bmkp-bmenu-kill-annotation, bmkp-remap.
+;; Bind bmkp-bmenu-show-this-annotation+move-(down|up) to M-down, M-up.
+;; bmkp-bmenu-describe-this+move-(down|up): Move first, then describe, not reverse.
+;; bmkp-bmenu-describe-this-bookmark: Wrap with save-selected-frame.
+;; 2015/02/22 dadams
+;; Moved to bookmark+-1.el from here:
+;; bmkp-reset-bmkp-store-org-link-checking-p, bmkp-store-org-link-checking-p.
+;; Advice of org-store-link (not needed for bmkp-bmenu-store-org-link).
+;; Soft-require org.el when compile, for org-add-link-type.
+;; bmkp-bmenu-store-org-link:
+;; Removed bmkp-store-org-link-checking-p (needed only for bmkp-store-org-link).
+;; Link type changed from bookmark-other-window to bookmark-other-win.
+;; Fix for lost annotation etc. edit the first time after showing display list:
+;; bookmark-bmenu-list, bmkp-bmenu-define-full-snapshot-command:
+;; Bind bookmark-alist to result of bmkp-refresh-latest-bookmark-list - do not just bind it to
+;; bmkp-latest-bookmark-alist if available. (NOT SURE THIS IS RIGHT.)
+;; bmkp-bmenu-list-1:
+;; Removed update of bmkp-latest-bookmark-alist when not filteredp. (NOT SURE THIS IS RIGHT.)
+;; bmkp-bmenu-menubar-menu:
+;; Toggle menu:
+;; Moved Toggle menu higher.
+;; Moved bmkp-toggle-save-desktop-before-switching with other autosaving menu items.
+;; Added bmkp-toggle-auto-light-when-jump-menu.
+;; Moved temporary bookmark stuff lower, after display-list stuff.
+;; bmkp-toggle-saving-menu-list-state: Corrected help text - affects also being able to save.
+;; Moved bmkp-list-defuns-in-commands-file with other help stuff.
+;; 2015/02/21 dadams
+;; Added: bmkp-bmenu-store-org-link, bmkp-reset-bmkp-store-org-link-checking-p,
+;; bmkp-store-org-link-checking-p.
+;; Add bmkp-bmenu-store-org-link to org-store-link-functions.
+;; Advise org-store-link with bmkp-reset-bmkp-store-org-link-checking-p.
+;; Added bookmark(-other-window) link types via org-add-link-type.
+;; 2015/02/08 dadams
+;; Added: bmkp-bmenu-show-only-untagged-bookmarks. Added it to bmkp-bmenu-show-types-menu.
+;; Renamed: bmkp-bmenu-*icicle-* to bmkp-bmenu-icicles-*,
+;; bmkp-bmenu-show-only-*- to bmkp-bmenu-show-only-*-bookmarks.
+;; Use new macro bmkp-define-show-only-command for the simple bmkp-bmenu-show-only-* commands.
+;; 2014/12/18 dadams
+;; bmkp-bmenu-show-only-specific-file: Restore vars if error.
+;; 2014/12/04 dadams
+;; *-dired-marked, *-move-marked-to-bookmark-file, *-copy-marked-to-bookmark-file,
+;; *-create-bookmark-file-from-marked, *-set-bookmark-file-bookmark-from-marked,
+;; *-(i)search-marked-bookmarks(-regexp), *-query-replace-marked-bookmarks-regexp,
+;; *-set-tag-value-for-marked, *-add-tags-to-marked, *-remove-tags-from-marked,
+;; *-paste-(add|replace)-tags-to-marked, *-relocate-marked, *-edit-marked, *-describe-marked:
+;; Added arg INCLUDE-OMITTED-P.
+;; 2014/11/09 dadams
+;; bookmark-bmenu-show-annotation: Updated doc string to reflect updated bookmark-show-annotation.
+;; 2014/08/22 dadams
+;; bmkp-looking-at-p: Do not defalias to Emacs looking-at-p because that is a defsubst.
+;; 2014/07/20 dadams
+;; Protect key bindings for bmkp-bmenu-highlight-menu by boundp.
+;; 2014/07/12 dadams
+;; Added: bmkp-bmenu-relocate-marked. Bound to M-R. Added it to bmkp-bmenu-menubar-menu.
+;; 2014/07/11 dadams
+;; bmkp-bmenu-highlight-menu: Added item Toggle Autofile Highlighting in Dired.
+;; bmkp-bmenu-toggle-menu: Added item Autofile Highlighting in Dired.
+;; 2014/07/06 dadams
+;; Toggle submenu: added lots, improved.
+;; 2014/07/05 dadams
+;; Added: bmkp-bmenu-create-bookmark-file-from-marked (bound to Y > 0),
+;; bmkp-bmenu-set-bookmark-file-bookmark-from-marked, bmkp-bmenu-bookmark-file-menu.
+;; Moved bookmark-file stuff to Bookmark File submenu.
+;; bookmark-bmenu-mode: Updated doc string.
+;; bmkp-bmenu-dired-marked: Use bmkp-bmenu-marked-or-this-or-all, not bmkp-marked-bookmarks-only.
+;; bmkp-bmenu-marked-or-this-or-all: Added optional arg INCLUDE-OMITTED-P - else removed omitted.
+;; 2014/07/04 dadams
+;; Added to Bookmark+ menu: bmkp-bmenu-(copy|move)-marked-to-bookmark-file.
+;; 2014/07/03 dadams
+;; Added: bmkp-bmenu-copy-marked-to-bookmark-file, bmkp-bmenu-move-marked-to-bookmark-file.
+;; Bound to Y > + and Y > -.
+;; bookmark-bmenu-mode: Mention bmkp-bmenu-(copy|move)-marked-to-bookmark-file in doc string.
+;; bookmark-bmenu-execute-deletions, bmkp-bmenu-delete-marked:: Added optional arg NO-CONFIRM-P.
+;; bmkp-bmenu-define(-full-snapshot|jump)-command: Changed to C-c C-c, C-c C-S-c, C-c C-j.
+;; bmkp-bmenu-show-all: Mention C-u g in doc string.
+;; 2014/06/30 dadams
+;; bmkp-bmenu-mouse-3-menu:
+;; Bind bmkp-bmenu-flag-for-deletion, not bookmark-bmenu-delete. See Emacs bug #17888.
+;; 2014/06/26 dadams
+;; bmkp-bmenu-show-only-omitted:
+;; Use bmkp-bmenu-omit/unomit-marked, not bmkp-bmenu-unomit-marked, in doc string.
+;; bmkp-bmenu-remove-tags-from-marked:
+;; Typo in interactive spec: allp -> current-prefix-arg. Thx to Alan Wehmann.
+;; 2014/06/21 dadams
+;; Added: bmkp-no-jump, bmkp-bmenu-mark-bookmark-list-bookmarks,
+;; bmkp-bmenu-mark-icicle-search-hits-bookmarks, bmkp-bmenu-show-only-bookmark-lists,
+;; bmkp-bmenu-show-only-icicle-search-hits.
+;; bookmark-bmenu-list, bookmark-bmenu-mode: Updated doc string, for additions.
+;; bmkp-bmenu-mode-status-help: Updated for no-jump (used for Icicles search hits bookmarks).
+;; bmkp-bmenu-propertize-item: Handle Icicles search hits bookmarks.
+;; Bind *-bmenu-mark-icicle-search-hits-bookmarks, *-bmenu-show-only-icicle-search-hits: i M, i S.
+;; Bind bmkp-bmenu-mark-bookmark-list-bookmarks, bmkp-bmenu-show-only-bookmark-lists: Z M, Z S.
+;; bmkp-bmenu-mark-types-menu:
+;; Added bmkp-bmenu-mark-icicle-search-hits-bookmarks, bmkp-bmenu-mark-bookmark-list-bookmarks.
+;; bmkp-bmenu-show-types-menu:
+;; Added bmkp-bmenu-show-only-icicle-search-hits, bmkp-bmenu-show-only-bookmark-lists.
+;; 2014/06/20 dadams
+;; bmkp-define-tags-sort-command: Load bookmark+-mac.el(c) in interactive spec.
+;; 2014/05/27 dadams
+;; bmkp-bmenu-mode-status-help, bmkp-bmenu-describe-marked:
+;; Use bmkp-with-help-window, not with-output-to-temp-buffer (Emacs 24.4+ silliness).
+;; 2014/04/02 dadams
+;; bmkp-bmenu-copy-tags, bmkp-bmenu-paste-replace-tags(for-marked):
+;; Added Note to doc string about pasting an empty list of tags.
+;; bmkp-bmenu-tags-menu: Added item Copy Tags from This Bookmark for bmkp-bmenu-copy-tags.
+;; bmkp-bmenu-mouse-3-menu: Added :active bmkp-copied-tags for bmkp-bmenu-paste-add-tags.
+;; 2014/04/01 dadams
+;; Added: bmkp-bmenu-list-tags-of-marked.
+;; Bind it to T > l in bookmark-bmenu-mode-map.
+;; Add it to bmkp-bmenu-tags-menu.
+;; bookmark-bmenu-mode: List bmkp-bmenu-list-tags-of-marked in doc string.
+;; 2014/03/29 dadams
+;; Added variable bmkp-bmenu-define-command-history.
+;; bmkp-bmenu-define(-jump-marked|-full-snapshot)-command:
+;; Removed quote before bmkp-bmenu-define-command-history.
+;; Toggle submenu: Use bmkp-menu-bar-make-toggle.
+;; 2014/03/28 dadams
+;; bmkp-bmenu-describe-marked: Apply bmkp-sort-omit, to show bookmarks in the current sort order.
+;; 2014/03/23 dadams
+;; Added: bmkp-bmenu-delete-menu, bmkp-bmenu-mark-types-menu, bmkp-bmenu-search-menu,
+;; bmkp-bmenu-show-types-menu, bmkp-bmenu-toggle-menu. Move menu items there from top.
+;; bookmark-bmenu-mode-map:
+;; Bind jump commands to j prefix and J prefix (like C-x 4 j and C-x j).
+;; Bind bookmark-bmenu-locate to C-S-l, since w is used as a prefix key now.
+;; bookmark-bmenu-mode: New jump bindings. Added bmkp-bmenu-copy-tags.
+;; 2014/03/21 dadams
+;; bookmark-bmenu-mode: List also global bindings for tag commands.
+;; 2014/03/10 dadams
+;; bmkp-maybe-unpropertize-bookmark-names: Remove prop face & Icicles props, in any case.
+;; bmkp-bmenu-define(-jump-marked|-full-snapshot)-command, bmkp-define-tags-sort-command:
+;; Bind print-circle to bmkp-propertize-bookmark-names-flag, not t, to avoid string reuse.
+;; 2013/12/13 dadams
+;; bmkp-bmenu-mode-line:
+;; To avoid Emacs crashes from bug #12867: Do not define it for Emacs 22-23, and wrap
+;; condition-case around the whole function body.
+;; 2013/12/11 dadams
+;; bmkp-bmenu-mode-line: Protect %360l (line) hack with condition-case.
+;; 2013/10/07 dadams
+;; bmkp-bmenu-edit-marked: If no marked bmks, mark the current line bmk, to start with.
+;; Use correct buffer when go to point-min.
+;; 2013/08/09 dadams
+;; Added: bmkp-looking-at-p. Use it instead of looking-at, everywhere.
+;; 2013/07/02 dadams
+;; Added to menu-bar Edit menu: bmkp-set-snippet-bookmark, bmkp-snippet-to-kill-ring.
+;; 2013/06/30 dadams
+;; Added: bmkp-snippet, bmkp-bmenu-show-only-snippets, bmkp-bmenu-mark-snippet-bookmarks.
+;; bookmark-bmenu-list: Added snippet info to doc string.
+;; bmkp-bmenu-mode-status-help: Cover snippets too.
+;; Bind bmkp-bmenu-(mark-snippet-bookmarks|show-only-snippets) to w M, w S. Add to menus.
+;; 2013/06/29 dadams
+;; bmkp-bmenu-regexp-mark, bmkp-bmenu-search-marked-bookmarks-regexp,
+;; bmkp-bmenu-(un)mark-bookmarks-tagged-regexp:
+;; Use bmkp-read-regexp in interactive spec.
+;; bmkp-bmenu-mode-status-help: Ensure that we have a supported image before calling insert-image.
+;; 2013/06/09 dadams
+;; bmkp-bmenu-mode-line-string: Added missing let-binding for REGEXP.
+;; Added vacuous defvars to suppress free-var warnings.
+;; 2013/05/28 dadams
+;; Renamed: bmkp-bmenu-edit-bookmark-name-and-file to bmkp-bmenu-edit-bookmark-name-and-location.
+;; 2013/05/28 dadams
+;; bmkp-bmenu-list-1: Do not call put-image if create-image returns nil.
+;; 2013/05/15 dadams
+;; Moved here from bookmark+-1.el: bmkp-string-match-p.
+;; Use bmkp-string-match-p instead of string-match wherever appropriate.
+;; 2013/04/10 dadams
+;; bmkp-bmenu-make-sequence-from-marked: Redefine using bmkp-set-sequence-bookmark (new).
+;; 2013/01/07 dadams
+;; bookmark-bmenu-mode:
+;; Added: bmkp-bmenu-set-tag-value-for-marked, bmkp-bmenu-paste-(add|replace)-tags-for-marked.
+;; Mention C-u = all, for marked.
+;; 2013/01/04 dadams
+;; bmkp-bmenu-show-only-tagged: Corrected filter function.
+;; 2012/11/14 dadams
+;; bmkp-bmenu-mode-line: Added mode-line-buffer-identification.
+;; 2012/11/12 dadams
+;; Added: bmkp-bmenu-marked-or-this-or-all.
+;; bmkp-bmenu-isearch-marked-bookmarks(-regexp), bmkp-bmenu-search-marked-bookmarks-regexp,
+;; bmkp-bmenu-query-replace-marked-bookmarks-regexp, bmkp-bmenu-set-tag-value-for-marked,
+;; bmkp-bmenu-add-tags-to-marked, bmkp-bmenu-remove-tags-from-marked,
+;; bmkp-bmenu-paste-(add|replace)-tags-(to|for)-marked, bmkp-bmenu-edit-marked,
+;; bmkp-bmenu-describe-marked:
+;; Make it work for current bookmark if none marked.
+;; bmkp-bmenu-isearch-marked-bookmarks(-regexp), bmkp-bmenu-search-marked-bookmarks-regexp,
+;; bmkp-bmenu-set-tag-value-for-marked, bmkp-bmenu-add-tags-to-marked,
+;; bmkp-bmenu-remove-tags-from-marked, bmkp-bmenu-paste-(add|replace)-tags-(to|for)-marked,
+;; bmkp-bmenu-edit-marked:
+;; Make it work for all bookmarks if use prefix arg.
+;; Protect all calls to bmkp-bmenu-mode-line with fboundp, for Emacs 20.
+;; 2012/11/11 dadams
+;; Added: bmkp-bmenu-mode-line, bmkp-bmenu-mode-line-string.
+;; Removed: bmkp-bmenu-nb-marked-in-mode-name (replaced by bmkp-bmenu-mode-line - shows more).
+;; Removed faces bmkp-mode-line-marked, bmkp-mode-line-flagged.
+;; bookmark-bmenu-(delete|(un)mark), bmkp-bmenu-list-1: Call bmkp-bmenu-mode-line.
+;; bookmark-bmenu-execute-deletions: Inhibit saving until all are deleted, then save.
+;; bmkp-bmenu-mode-status-help: Show > and D using their faces, bmkp->-mark, bmkp-D-mark.
+;; Use "" if bmkp-current-sort-order (new version) returns nil.
+;; 2012/10/09 dadams
+;; Made all autoload cookies explicitly load bookmark+.el(c). Should help ELPA (e.g. MELPA).
+;; 2012/09/29 dadams
+;; Added: bmkp-maybe-unpropertize-string.
+;; bmkp-maybe-unpropertize-bookmark-names: Added optional arg COPY.
+;; bmkp-bmenu-define(-jump-marked|-full-snapshot|-tags-sort)-command:
+;; Bind print-circle, version-control, require-final-newline.
+;; Use find-file-noselect & write-file, not write-region.
+;; bmkp-bmenu-define-jump-marked-command: Use bmkp-maybe-unpropertize-bookmark-names on bookmarks.
+;; bmkp-bmenu-define-full-snapshot-command:
+;; Copy shared bookmark lists and single strings, to avoid circular refs.
+;; Expand file names and use convert-standard-filename, for bookmark file names.
+;; 2012/09/28 dadams
+;; Added: bmkp-bmenu-jump-to-marked.
+;; Renamed: bmkp-bmenu-w32-open-select to bmkp-bmenu-w32-jump-to-marked.
+;; Replace bookmark-bmenu-select with bmkp-bmenu-jump-to-marked, everywhere.
+;; bmkp-bmenu-w32-open-with-mouse:
+;; Rewrote to directly call bookmark-handle-bookmark, jump-fn, and show annotations.
+;; 2012/09/03 dadams
+;; bookmark-bmenu-toggle-filenames: Added missing nil FORCE arg.
+;; bmkp-bmenu-list-1: Call bookmark-bmenu-toggle-filenames with NO-MSGP arg.
+;; Removed: bmkp-bmenu-filter-prompt. bmkp-bmenu-read-filter-input: hard-code the prompt.
+;; 2012/06/26 dadams
+;; Moved here from bookmark+-mac.el: bmkp-assoc-delete-all, bmkp-replace-regexp-in-string.
+;; Wrapped require of bookmark+-mac.el in eval-when-compile.
+;; 2012/06/21 dadams
+;; Added: bmkp-bmenu-nb-marked-in-mode-name. Added to bookmark-bmenu-mode-hook.
+;; Try to load-library bookmark+-mac. Require it only if cannot load-library.
+;; 2012/06/15 dadams
+;; bookmark-bmenu-mode, bmkp-bmenu-mode-status-help: Improved doc string.
+;; bmkp-bmenu-show-or-edit-annotation: Corrected doc string: bookmark, not buffer.
+;; 2012/06/14 dadams
+;; Added face bmkp-no-local.
+;; Redefined defaults for faces bmkp-non-file and bmkp-variable-list.
+;; bmkp-bmenu-mode-status-help: Added legend for no such local file.
+;; bmkp-bmenu-propertize-item: Distinguish no such local file from no such existing buffer.
+;; 2012/06/13 dadams
+;; bookmark-bmenu-bookmark: forward-char bmkp-bmenu-marks-width, not 1+ that.
+;; bmkp-bmenu-propertize-item: Allow a file bookmark to get buffer prop if file not yet saved.
+;; Do not require buffer-name attribute for bmkp-non-file face.
+;; 2012/06/11 dadams
+;; bmkp-bmenu-propertize-item: Use bmkp-non-file-filename also if filename is missing from bmk.
+;; 2012/05/05 dadams
+;; bookmark-bmenu-(un)mark(-all), bmkp-bmenu-regexp-mark, bmkp-bmenu-toggle-marks,
+;; bmkp-bmenu-mark-bookmarks-satisfying, bmkp-bmenu-toggle-marked-temporary/savable,
+;; bmkp-bmenu-(un)mark-bookmarks-tagged-regexp:
+;; Added optional arg MSG-P.
+;; bookmark-bmenu-(un)mark(-all), bookmark-bmenu-execute-deletions, bmkp-bmenu-regexp-mark,
+;; bmkp-bmenu-toggle-show-only-(un)marked, bmkp-bmenu-mark-bookmarks-satisfying,
+;; bmkp-bmenu-toggle-marks, bmkp-bmenu-toggle-marked-temporary/savable,
+;; bmkp-bmenu-toggle-temporary, bmkp-bmenu-make-sequence-from-marked,
+;; bmkp-bmenu-(un)omit(-marked), bmkp-bmenu-(un)mark-bookmarks-tagged-regexp,
+;; bmkp-bmenu-mark/unmark-bookmarks-tagged-*, bmkp-bmenu-change-sort-order,
+;; bmkp-reverse(-multi)-sort-order:
+;; Pass NO-MSG-P to *-refresh/rebuild-menu-list, *-surreptitiously-rebuild-list, *-store.
+;; bmkp-bmenu-mark/unmark-bookmarks-tagged-(all/none|some/not-all):
+;; Swapped last two args, so consistent order.
+;; bmkp-bmenu-(un)mark-bookmarks-tagged-*: Updated arg order in calls to b-b-m/u-b-t-(a/n|s/n-a).
+;; bmkp-bmenu-(un)mark-bookmarks-tagged-regexp, bmkp-bmenu-mark/unmark-bookmarks-tagged-*:
+;; Added status message.
+;; 2012/05/01 dadams
+;; Added redefinition of bookmark-bmenu-delete-backwards (they broke its movement).
+;; Added aliases: bmkp-bmenu-flag-for-deletion(-backwards). Bind to d, k, C-d (same as aliases).
+;; bmkp-bmenu-(add|remove)-tags, bmkp-bmenu-(add|remove)-tags-(to|from)-marked:
+;; Automatically re-sort if # tagged bmks changed and sort order is tagged first/last (s t).
+;; Added: bmkp-bmenu-sort-tagged-before-untagged.
+;; Bind bmkp-bmenu-sort-tagged-before-untagged to s t.
+;; Bind bmkp-bmenu-sort-by-last-bookmark-access to s d, not s t.
+;; Bind bmkp-bmenu-sort-by-last-local-file-access to s f d, not s f t.
+;; Bind bmkp-bmenu-sort-by-local-file-type to s f k, not s f d.
+;; 2012/04/28 dadams
+;; bookmark-bmenu-(un)mark(-all), bmkp-bmenu-regexp-mark, bmkp-bmenu-mark-bookmarks-satisfying,
+;; bmkp-bmenu-toggle-marks, bmkp-bmenu-(un)mark-bookmarks-tagged-regexp,
+;; bmkp-bmenu-mark/unmark-bookmarks-tagged-(all/none|some/not-all):
+;; Added optional arg NO-RE-SORT-P.
+;; Automatically re-sort if marks changed and if sort order is marked first/last (s >).
+;; Changed all non-interactive calls of bookmark-bmenu-(un)mark to pass non-nil NO-RE-SORT-P.
+;; bmkp-bmenu-toggle-marks: Call bookmark-bmenu-ensure-position at start.
+;; 2012/04/27 dadams
+;; bmkp-bmenu-edit-marked: Use bmkp-with-output-to-plain-temp-buffer.
+;; 2012/04/13 dadams
+;; Added: bmkp-bmenu-sort-(flagged|modified)-before-un(flagged|modified), bmkp-flagged-bookmarks.
+;; Bound bmkp-bmenu-sort-(flagged|modified)-before-un(flagged|modified) to s D, s *.
+;; bookmark-bmenu-(un)mark: Delete bookmark from bmkp-flagged-bookmarks.
+;; bookmark-bmenu-mark: Use (equivalent of) eq version of add-to-list.
+;; bookmark-bmenu-delete: Add bookmark to bmkp-flagged-bookmarks.
+;; bmkp-bmenu-list-1: Always reset bmkp-(flagged|modified)-bookmarks.
+;; Flag bookmarks if bmkp-flagged-bookmark-p.
+;; bmkp-bmenu-refresh-menu-list: C-u resets bmkp-flagged-bookmarks too.
+;; 2012/04/10 dadams
+;; bmkp-bmenu-load-marked-bookmark-file-bookmarks:
+;; Use bmkp-refresh-menu-list, not bmkp-refresh/rebuild-menu-list.
+;; bmkp-bmenu-(add|remove)-tags-(to|from)-marked, bmkp-bmenu-paste-(add|replace)-tags-to-marked:
+;; Corrected bookmark-save to bookmark-save-flag in bindings to nil.
+;; Use bmkp-count-multi-mods-as-one-flag for the binding.
+;; Call bmkp-refresh-menu-list.
+;; 2012/04/09 dadams
+;; bmkp-bmenu-set-tag-value, bmkp-bmenu-remove-tags, bmkp-bmenu-paste-(add|replace)-tags:
+;; Added nil NO-UPDATE-P arg in calls to bmkp-set-tag-value, bmkp-remove-tags,
+;; bmkp-paste-(add|replace)-tags.
+;; bmkp-bmenu-add-tags-to-marked, bmkp-bmenu-remove-tags-from-marked,
+;; bmkp-bmenu-paste-(add|replace)-tags-to-marked:
+;; Bind bookmark-save to nil around iteration, to inhibit saving until finished.
+;; New arg order for calls to bmkp-(add|remove)-tags.
+;; Pass non-nil NO-UPDATE-P arg to bmkp-paste-(add|replace)-tags.
+;; 2012/04/03 dadams
+;; Moved here from bookmark+-1.el: bmkp-face-prop.
+;; 2012/03/19 dadams
+;; Added: bmkp-*-mark.
+;; bmkp-bmenu-list-1, bmkp-bmenu-mode-status-help: Use bmkp-*-mark for *.
+;; 2012/03/18 dadams
+;; bookmark-bmenu-delete: Remove bookmark from bmkp-modified-bookmarks also.
+;; bmkp-bmenu-list-1: RESET-P resets bmkp-modified-bookmarks also. Insert modified marks (*).
+;; bmkp-bmenu-refresh-menu-list:
+;; When revert from file: Reset *-marked-bookmarks, *-modified-bookmarks, *-omitted-bookmarks.
+;; Bind bmkp-bmenu-filter-function to nil for bmkp-refresh-menu-list.
+;; bmkp-bmenu-toggle-show-only-(un)marked:
+;; Save display, so bmkp-bmenu-before-hide-marked-alist is up-to-date.
+;; bmkp-bmenu-mode-status-help: Added legend for markings.
+;; bmkp-bmenu-edit-marked: Use (shallow) copies of bookmarks, not originals.
+;; Added bmkp-save-menu-list-state to Bookmark+ menu.
+;; 2012/03/13 dadams
+;; bmkp-bmenu-read-filter-input:
+;; If C-g then restore previous display.
+;; Use only one catch and test while condition.
+;; Do not try to pop an empty list.
+;; bmkp-bmenu-filter-((bookmark|file)-name|annotation|tags)-incrementally:
+;; Use run-with-idle-timer, not run-with-timer
+;; 2012/03/11 dadams
+;; Added Revert to Saved (bmkp-revert-bookmark-file) to menu.
+;; 2012/03/07 dadams
+;; bmkp-bmenu-load-marked-bookmark-file-bookmarks: Use bmkp-sorted-alist to load in display order.
+;; 2012/03/06 dadams
+;; bookmark-bmenu-mode: Reorg.
+;; bmkp-bmenu-refresh-menu-list:
+;; Call bmkp-refresh-menu-list also when revert file. Use yes-or-no-p, not y-or-n-p.
+;; 2012/03/05 dadams
+;; bmkp-bmenu-mode-status-help: Added Autosave bookmarks and Autosave list display to info at top.
+;; 2012/03/04 dadams
+;; Added: bmkp-bmenu-load-marked-bookmark-file-bookmarks.
+;; Bind bmkp-toggle-saving-menu-list-state to C-M-~, not M-l.
+;; Bind bmkp-bmenu-load-marked-bookmark-file-bookmarks to M-l. Add it to menu.
+;; 2012/03/02 dadams
+;; bookmark-bmenu-list: Reset marked and omitted lists to () if a name is not a current bmk.
+;; 2012/02/28 dadams
+;; Added face bmkp-file-handler.
+;; bmkp-bmenu-mode-status-help: Added bmkp-file-handler to face legend.
+;; bmkp-bmenu-propertize-item: Propertize file-handler bookmarks, with bmkp-file-handler.
+;; 2011/12/31 dadams
+;; Define macro with-buffer-modified-unmodified for Emacs 23.1, in addition to Emacs < 23.
+;; 2011/12/30 dadams
+;; Added aliases: bmkp-bookmark-(data|name)-from-record.
+;; Added: bmkp-bmenu-show-or-edit-annotation, bmkp-bmenu-edit-bookmark-record,
+;; bmkp-bmenu-edit-marked.
+;; Renamed bmkp-bmenu-edit-bookmark to bmkp-bmenu-edit-bookmark-name-and-file.
+;; bookmark-bmenu-mark: Propertize bookmark name with bmkp-full-record before adding to list.
+;; bookmark-bmenu-list:
+;; Added optional arg MSGP. Show status messages.
+;; Propertize bookmark names if not already propertized, in marked and omitted lists.
+;; bookmark-bmenu-mode: Updated doc string.
+;; bmkp-bmenu-make-sequence-from-marked:
+;; Use bmkp-get-bookmark-in-alist, not bookmark-get-bookmark.
+;; Bind bmkp-bmenu-show-or-edit-annotation (not *-show-annotation) to a.
+;; Bind bmkp-bmenu-edit-bookmark-name-and-file to r now, not E.
+;; Bind bmkp-bmenu-edit-marked to E and T > e.
+;; Bind bmkp-bmenu-edit-bookmark-record to e.
+;; bmkp-bmenu-quit: Show progress messages.
+;; bmkp-bmenu-tags-menu: Added bmkp-bmenu-edit-marked.
+;; bmkp-bmenu-mouse-3-menu:
+;; Added: bmkp-bmenu-edit-tags.
+;; Replaced *-rename and *-relocate with bmkp-bmenu-edit-bookmark-name-and-file.
+;; 2011/12/24 dadams
+;; Added: bookmark-bmenu-toggle-filenames, with optional arg NO-MSG-P.
+;; bookmark-bmenu-surreptitiously-rebuild-list, bookmark-bmenu-(show|hide)-filenames:
+;; Added progress messages and optional arg NO-MSG-P.
+;; bookmark-bmenu-(show|hide)-filenames, bookmark-bmenu-toggle-filenames:
+;; Correct FORCE behavior and doc strings.
+;; bmkp-bmenu-refresh-menu-list: Pass (not) MSG-P to bmkp-refresh-menu-list.
+;; 2011/12/21 dadams
+;; Added: bmkp-bmenu-mark-orphaned-local-file-bookmarks,
+;; bmkp-bmenu-show-only-orphaned-local-files, bmkp-bmenu-mark-variable-list-bookmarks.
+;; bmkp-bmenu-refresh-menu-list: Added optional args ARG and MSGP, so you can revert from file.
+;; bookmark-bmenu-mode: Updated and reordered doc string.
+;; Bind O M, O S to orphaned commands, not omit commands. Changed omit bindings to use -, not O.
+;; Bind bmkp-bmenu-mark-variable-list-bookmarks to V M.
+;; bmkp-bmenu-show-menu: Reordered. Added: *-w3m-urls, *-variable-lists, *-orphaned-local-files.
+;; bmkp-bmenu-mark-menu: Reordered. Added: *-w3m-*, *-variable-list-*, *-orphaned-local-file-*.
+;; 2011/12/19 dadams
+;; Added: with-buffer-modified-unmodified.
+;; bookmark-bmenu-((un)mark|delete), bookmark-bmenu-(show|hide)-filenames:
+;; Use with-buffer-modified-unmodified.
+;; bookmark-bmenu-show-filenames, bmkp-bmenu-mouse-3-menu: Use line-(beginning|end)-position.
+;; 2011/12/15 dadams
+;; bmkp-bmenu-propertize-item: Use bmkp-local-directory face also for Dired (e.g. with wildcards).
+;; bmkp-bmenu-mode-status-help: Clarify legend for remote and local dirs/Dired.
+;; 2011/12/08 dadams
+;; bmkp-bmenu-mouse-3-menu: Use easymenu to build the menu. Conditionalize some items.
+;; Bind down-mouse-3, not mouse-3, to bmkp-bmenu-mouse-3-menu. (bind mouse-3 to ignore).
+;; Added eval-when-compile for easymenu.el.
+;; 2011/12/05 dadams
+;; bmkp-bmenu-menubar-menu: Reordered items regarding bookmark files.
+;; bmkp-bmenu-mode-status-help: Correct intro text, reorder, use marker for position TOP.
+;; bookmark-bmenu-mode: Changed intro text slightly.
+;; 2011/12/03 dadams
+;; bmkp-bmenu-list-1: Print current bookmark file at top of display.
+;; Increased bmkp-bmenu-header-lines to 5.
+;; bookmark-bmenu-mode: Updated doc string for binding changes and new option.
+;; bmkp-bmenu-regexp-mark: Mention right-padding of bookmark names in doc string.
+;; bmkp-bmenu-mode-status-help: Reorder Current Status items, to put bookmark file first.
+;; Bind L to bmkp-switch-bookmark-file-create, not bmkp-switch-bookmark-file.
+;; 2011/11/19 dadams
+;; bmkp-bmenu-image-bookmark-icon-file: Default to an existing Emacs image file, not nil.
+;; 2011/11/18 dadams
+;; Added: bmkp-bmenu-mark-image-bookmarks, bmkp-bmenu-show-only-image-files,
+;; bmkp-bmenu-image-bookmark-icon-file.
+;; bmkp-bmenu-list-1: Show icon image for image-file bookmarks.
+;; bookmark-bmenu-mode: Add to doc string: bmkp-image-jump, bmkp-bmenu-mark-image-bookmarks,
+;; bmkp-bmenu-show-only-image-files.
+;; bmkp-bmenu-mode-status-help: Added image icon to legend.
+;; Bound keys: M-I M-M, M-I M-S to *-mark-image-bookmarks *-show-only-image-files.
+;; Added to menus (Mark, Show): bmkp-bmenu-mark-image-bookmarks, bmkp-bmenu-show-only-image-files.
+;; 2011/11/01 dadams
+;; bookmark-bmenu-mode: Changed mode-name var for mode line: Bookmarks, not Bookmark Menu.
+;; Updated doc string for autofile & temporary jump commands.
+;; 2011/10/31 dadams
+;; bookmark-bmenu-mode: Updated doc string with bmkp-toggle-autotemp-on-set.
+;; bmkp-bmenu-menubar-menu: Added: bmkp-toggle-autotemp-on-set.
+;; 2011/10/27 dadams
+;; Added: bmkp-X-mark, bmkp-bmenu-toggle-marked-temporary/savable, bmkp-bmenu-toggle-temporary,
+;; bmkp-bmenu-mark-autonamed-bookmarks, bmkp-bmenu-show-only-temporary,
+;; bmkp-bmenu-mark-temporary-bookmarks.
+;; bmkp-bmenu-list-1: Mark with X in place of a, if bookmark is temporary.
+;; bookmark-bmenu-mode: Mode-line major-mode name indicates when in temporary bookmarking mode.
+;; Updated doc string with temporary bookmark commands.
+;; bmkp-t-mark: Changed default attributes.
+;; Bind: M-L to bmkp-temporary-bookmarking-mode, M-X to bmkp-bmenu-toggle-marked-temporary/savable
+;; X M to bmkp-bmenu-mark-temporary-bookmarks, X S to bmkp-bmenu-show-only-temporary,
+;; C-M-X to bmkp-bmenu-toggle-temporary.
+;; bmkp-bmenu-show-only-bookmark-files: Bind to Y S, not X S.
+;; bmkp-bmenu-mark-bookmark-file-bookmarks: Bind to Y M, not X M.
+;; 2011/07/01 dadams
+;; bmkp-bmenu-change-sort-order, bmkp(-multi)-reverse-sort-order: Handle null CURRENT-BMK.
+;; 2011/04/24 dadams
+;; Added to Tags menu: Purge Autofiles with No Tags.
+;; 2011/04/23 dadams
+;; Bound bmkp-bmenu-set-tag-value-for-marked to T > v and added to bmkp-bmenu-tags-menu.
+;; bmkp-bmenu-mouse-3-menu: Added bmkp-rename-tag.
+;; 2011/04/22 dadams
+;; Bound *-copy-tags to T c, T M-w, *-paste(-add|replace)-tags to T p, T C-y, T q.
+;; 2011/04/21 dadams
+;; Added: bmkp-bmenu-copy-tags, bmkp-bmenu-paste-add-tags(-to-marked),
+;; bmkp-bmenu-paste-replace-tags(-for-marked).
+;; Bound and added to menus: bmkp-bmenu-paste-add-tags-to-marked,
+;; bmkp-bmenu-paste-replace-tags-for-marked.
+;; Added to This Bookmark menu: bmkp-bmenu-copy-tags, bmkp-bmenu-paste(-add|replace)-tags.
+;; 2011/04/19 dadams
+;; Added: bmkp-bmenu-unmark-bookmarks-tagged-regexp. Bound it to T u %. Added it to menu.
+;; 2011/04/16 dadams
+;; Added: bmkp-edit-tags-send. Bound it to T e in bookmark-bmenu-mode-map.
+;; bookmark-bmenu-mode: Updated help text for tags editing.
+;; bmkp-maybe-unpropertize-bookmark-names:
+;; Test emacs-major-version, not just (boundp 'print-circle).
+;; 2011/04/15 dadams
+;; Added: bmkp-bmenu-mark-autofile-bookmarks, bmkp-bmenu-show-only-autofiles.
+;; And added them to menus.
+;; bookmark-bmenu-mode-map:
+;; Bind bmkp-bmenu-mark-autofile-bookmarks, bmkp-bmenu-show-only-autofiles to A M, A S.
+;; Bind bookmark-bmenu-show-all-annotations to M-a, not A.
+;; Bind bmkp-bmenu-search-marked-bookmarks-regexp to M-s a M-s, not M-a.
+;; Bind *-mark-url-bookmarks, *-show-only-urls to M-u M-m, M-u M-s, not M-u M, M-u S.
+;; bookmark-bmenu-mode: Updated help to reflect latest bindings.
+;; 2011/04/13 dadams
+;; bmkp-bmenu-tags-menu: Added: bmkp-(un)tag-a-file.
+;; 2011/04/12
+;; Added: bmkp-propertize-bookmark-names-flag, bmkp-maybe-unpropertize-bookmark-names,
+;; bmkp-bmenu-get-marked-files.
+;; Renamed: bmkp-bmenu-omitted-list to bmkp-bmenu-omitted-bookmarks.
+;; bmkp-bmenu-define-full-snapshot-command:
+;; Bind print-circle to t around pp. Use bmkp-maybe-unpropertize-bookmark-names on lists.
+;; bookmark-bmenu-(show|hide)-filenames, bmkp-bmenu-toggle-show-only-(un)marked,
+;; bmkp-bmenu-(un)omit-marked:
+;; Fit one-window frame only if selected window is *Bookmark List*.
+;; bookmark-bmenu-bookmark: Added optional arg FULL. Non-nil means return full bookmark record.
+;; bookmark-bmenu-unmark, bookmark-bmenu-delete, bmkp-bmenu-unomit-marked:
+;; Use bmkp-delete-bookmark-name-from-list, not delete.
+;; bookmark-bmenu-execute-deletions: Pass full bookmark, not name, to delete, and don't use assoc.
+;; bookmark-bmenu-rename: Use bmkp-bmenu-goto-bookmark-named instead of just searching for name.
+;; bmkp-bmenu-toggle-marks, bmkp-bmenu-unomit-marked, bmkp-bmenu-define-jump-marked-command,
+;; bmkp-bmenu-mouse-3-menu:
+;; Use bmkp-bookmark-name-member, not member.
+;; bmkp-bmenu-make-sequence-from-marked: Do not invoke bookmark-bmenu-list when no displayed list.
+;; bmkp-bmenu-define-command: Use bmkp-maybe-unpropertize-bookmark-names on *-omitted-bookmarks.
+;; bmkp-bmenu-list-1: Use bmkp-sort-omit, not bmkp-sort-and-remove-dups.
+;; Pass full bookmark to bmkp-bmenu-propertize-item.
+;; bmkp-bmenu-propertize-item:
+;; First arg is now a full bookmark, not a bookmark name. Get bookmark name from it.
+;; Put prop bmkp-bookmark-name on buffer text with propertized bookmark-name string as value.
+;; String has property bmkp-full-record with value the full bookmark record, with string as car.
+;; Return propertized bookmark-name string.
+;; bmkp-bmenu-isearch-marked-bookmarks(-regexp), bmkp-bmenu-dired-marked,
+;; bmkp-bmenu-(search|query-replace)-marked-bookmarks-regexp:
+;; Use bmkp-sort-omit, not bmkp-sort-and-remove-dups.
+;; bmkp-bmenu-goto-bookmark-named:
+;; If NAME has property bmkp-full-record then go to the bookmark it indicates. Otherwise, just
+;; go to the first bookmark with the same name.
+;; bookmark-bmenu-mode: Added bmkp-save-menu-list-state (now a command) to the mode help.
+;; 2011/04/02 dadams
+;; bookmark-bmenu-mode: Added to mode help: bmkp-file-this-dir-(all|some)-tags(-regexp)-jump.,
+;; Create/Set section, with bmkp-autofile-set.
+;; 2011/04/01 dadams
+;; bookmark-bmenu-mode: Added to mode help: bmkp-(dired|file)-this-dir-jump.
+;; 2011/03/26 dadams
+;; bookmark-bmenu-mode: Added new file-with-tags jump commands to the help.
+;; 2011/03/05 dadams
+;; bmkp-bmenu-edit-bookmark: Use bmkp-refresh-menu-list, not *-surreptitiously-rebuild-list.
+;; 2011/02/11 dadams
+;; Faces: Better defaults for dark background.
+;; 2011/01/03 dadams
+;; Removed autoload cookies from non def* sexps and from define-key.
+;; Added missing autoload cookies for commands, in particular redefined std commands & defalias.
+;; 2010/12/10 dadams
+;; Added defalias for bookmark-name-from(-full)-record, to fix gratuitous Emacs name change.
+;; 2010/09/24 dadams
+;; Added: bmkp-bmenu-show-only-autonamed. Bound to # S. Added to bmkp-bmenu-show-menu.
+;; bookmark-bmenu-mode: Updated doc string for autonamed jumps, show.
+;; Renamed varlist to variable-list everywhere.
+;; 2010/08/22 dadams
+;; Added: bmkp-bmenu-filter-annotation-incrementally, bookmark-bmenu-relocate (Emacs 20, 21),
+;; bmkp-bmenu-filter-alist-by-annotation-regexp. Bound, added to menus and help.
+;; 2010/08/18 dadams
+;; Removed eval-when-compile for bookmark+-(lit|1).el.
+;; bmkp-bmenu-propertize-item: Inconsequential simplification.
+;; 2010/08/17 dadams
+;; bmkp-bmenu-edit-bookmark: Added optional arg INTERNALP (prefix arg), for editing record.
+;; 2010/08/15 dadams
+;; Moved to bookmark+-mac.el:
+;; bmkp-define-sort-command, bmkp-replace-regexp-in-string, bmkp-assoc-delete-all.
+;; Renamed: bmkp-barf-if-not-in-menu-list to bmkp-bmenu-barf-if-not-in-menu-list.
+;; Require bookmark.el, bookmark+-mac.el.
+;; Require when compile: bookmark+-1.el, bookmark+-lit.el (soft).
+;; 2010/07/17 dadams
+;; Added: bmkp-bmenu-mark-url-bookmarks, bmkp-bmenu-show-only-urls, bmkp-bmenu-sort-by-url.
+;; Removed: bmkp-bmenu-sort-by-w3m-url.
+;; Replaced face bmkp-w3m by bmkp-url.
+;; bookmark-bmenu-mode: Added mark and show URL commands.
+;; bookmark-bmenu-mode, *-status-help, *-sort-by-bookmark-type, *-define-sort-command: w3m -> url.
+;; Bind bmkp-bmenu-sort-by-url, not bmkp-bmenu-sort-by-w3m-url.
+;; Bind bmkp-bmenu-mark-url-bookmarks, bmkp-bmenu-show-only-urls.
+;; Replace W3M by URL in menu items.
+;; 2010/07/14 dadams
+;; Created from bookmark+.el code.
+
+;;;(@* "CHANGE LOG FOR `bookmark+-doc.el'")
+;;
+;; 2020/07/04 dadams
+;; Changed all references to `C-x p' to `C-x x'.
+
+;;;(@* "CHANGE LOG FOR `bookmark+-key.el'")
+;;
+;; 2021/09/19 dadams
+;; Everywhere: Use bmkp-bmenu-buffer, not vanilla bookmark-bmenu-buffer.
+;; 2021/02/12 dadams
+;; Typo in eval-after-load for EWW: previous -> next.
+;; 2020/07/04 dadams
+;; Changed all `C-x p' to `C-x x'.
+;; Replaced string *Bookmark List* with bookmark-bmenu-buffer (for Emacs 28).
+;; 2020/06/20 dadams
+;; Correctly added bmkp-compilation-target-set(-all) to compilation and grep maps.
+;; 2020/01/27 dadams
+;; Bind bookmark-jump-other-frame to 5 in bookmark-map.
+;; 2020/01/25 dadams
+;; bmkp-bookmarks-here-menu-command-entries:
+;; Added bmkp-edit-bookmark-record-file/buffer, bmkp-set-lighting-for-this-buffer,
+;; bmkp-unlight-this-buffer, bmkp-(un)light-(non-)autonamed-this-buffer
+;; Use bmkp-light-this-buffer, not bmkp-light-bookmarks.
+;; menu-bar-bookmark-map > bmkp-here-menu: Rename; use bmkp-exists-this-file/buffer-bookmarks-p.
+;; 2020/01/24 dadams
+;; Added: bmkp-annotate-map, bmkp-annotate-menu.
+;; bmkp-bookmarks-here-menu-command-entries, bmkp-highlight-menu:
+;; Added: bmkp-describe-bookmark-lighted-here.
+;; bmkp-bookmarks-here-menu-command-entries:
+;; Added: bmkp-light-bookmarks, bmkp-bookmarks-lighted-at-point,
+;; bmkp-annotate-bookmark-this-file/buffer, bmkp-annotate-all-bookmarks-this-file/buffer.
+;; Bind annotation commands to prefix C-x p a (bmkp-annotate-map).
+;; Move Here submenu before Highlight submenu.
+;; Typo in name when binding: bmkp-this-file/buffer-bmenu-list.
+;; 2020/01/22 dadams
+;; Bind bmkp-switch-to-bookmark-file-this-file/buffer to C-x p C-l,
+;; bmkp-save-bookmarks-this-file/buffer to C-x p C-s.
+;; Change bmkp-jump-to-list from C-x [pj] C-l to C-x [pj] C-j.
+;; bmkp-bookmarks-here-menu-command-entries:
+;; Added bmkp-(switch-to-bookmark-file|save-bookmarks)-this-file/buffer.
+;; 2019/08/13 dadams
+;; Bind bmkp-clone-bookmark to C-x p 2.
+;; menu-bar-bookmark-map: Add bmkp-clone-bookmark.
+;; 2019/05/16 dadams
+;; Added: bmkp-add-bookmarks-here-menu-flag, bmkp-here-menu, bmkp-exists-bookmark-satisfying-p,
+;; bmkp-exists-this-file/buffer-bookmarks-p, bmkp-bookmarks-here-menu-command-entries,
+;; Add bmkp-here-menu to menu-bar-bookmark-map, Buffer-menu-mode-map, Info-mode-menu,
+;; diredp-bookmark-menu or dired-mode-map.
+;; Add bmkp-dired-this-dir-jump to diredp-bookmark-menu or dired-mode-map.
+;; 2019/05/01 dadams
+;; Bind bmkp-jump-to-list to C-x p C-l, C-x j C-l.
+;; 2019/04/22 dadams
+;; Bind bmkp-describe-bookmark to C-h M, bmkp-describe-bookmark-lighted-here to C-x p ?.
+;; 2018/10/10 dadams
+;; Bound bookmark-jump-other-frame to C-x 5 B, C-x j 5 globally, and J 5 in bookmark-list buffer.
+;; 2017/10/14 dadams
+;; All EWW stuff is for Emacs 25+, not Emacs 24.4+.
+;; 2017/01/10 dadams
+;; Applied renaming: bmkp-replace-eww-keys-flag to bmkp-eww-replace-keys-flag.
+;; 2017/01/02 dadams
+;; menu-bar-bookmark-map: Added menu item Store Org Link To....
+;; Typo: bmkp-replace-EWW-keys-flag -> bmkp-replace-eww-keys-flag.
+;; 2016/12/11 dadams
+;; Remap EWW keys to bmkp- keys.
+;; 2016/11/23 dadams
+;; Put :advertised-binding on several keys.
+;; 2016/11/15 dadams
+;; bmkp-eww-jump(-other-window): Ensure that EWW code is only for Emacs 25+.
+;; 2016/11/14 dadams
+;; Added bindings for bmkp-eww-jump(-other-window), including in eww-mode-map.
+;; Bind bmkp-delete-bookmarks to kill-line keys (C-x p C-k, C-x p deleteline).
+;; 2016/06/24 dadams
+;; Added bmkp-delete-bookmarks binding for <deletechar> and <kp-delete>.
+;; 2016/05/15 dadams
+;; dired-mode-hook:
+;; If diredp-bookmark-menu is defined then use that.
+;; Rename menu item: Show This Dir Using a Bookmark -> Jump to a Dired Bookmark For This Dir.
+;; 2016/05/08 dadams
+;; Added: bmkp-bookmark-map-prefix-key, bmkp-jump-map-prefix-key,
+;; bmkp-jump-other-window-map-prefix-key, bmkp-set-map-prefix-key.
+;; Removed hard-coded bindings for keymaps in ctl-x-map, ctl-x-4-map.
+;; (eval-when-compile (require 'cl)) ;; case
+;; 2015/01/04 dadams
+;; Bind bmkp-region-jump-narrow-indirect-other-window to C-x 4 j R.
+;; 2014/07/11 dadams
+;; bmkp-highlight-menu: Added item Toggle Autofile Highlighting in Dired.
+;; 2014/07/06 dadams
+;; Removed: bmkp-options-menu. Use bmkp-bmenu-toggle-menu, and rename Toggle, not Toggle Option.
+;; Removed individual toggle commands from menu-bar-bookmark-map (Bookmarks).
+;; Reuse bmkp-bmenu-toggle-menu for menu-bar-bookmark-map [options].
+;; 2014/07/05 dadams
+;; Moved submenu bmkp-jump-tags-menu before individual menu items.
+;; 2014/03/23 dadams
+;; Bind j and J in bookmark-bmenu-mode-map. Bind also j > there.
+;; Add bmkp-bmenu-jump-to-marked to bmkp-jump-menu when in bookmark-list display.
+;; 2013/10/29 dadams
+;; Bind bookmark-set's previous keys to bmkp-bookmark-set-confirm-overwrite.
+;; Bind bookmark-set to C-x r M, not C-x r m.
+;; bmkp-menu-bar-set-bookmark: Use bmkp-bookmark-set-confirm-overwrite, not bookmark-set.
+;; 2013/07/20 dadams
+;; Moved items to new submenus: New/Update and Delete.
+;; 2013/06/30 dadams
+;; Bind bmkp-set-snippet-bookmark to C-x p M-w, bmkp-snippet-to-kill-ring to C-x j M-w.
+;; 2013/05/28 dadams
+;; Applied renaming of bmkp-edit-bookmark-name-and-file to bmkp-edit-bookmark-name-and-location.
+;; 2013/04/15 dadams
+;; In bmkp-set-map: Bind F to bmkp-make-function-bookmark (C-x p c F).
+;; Bind C-k to bmkp-wrap-bookmark-with-last-kbd-macro (C-x p c C-k).
+;; Bind s to bmkp-set-sequence (C-x p c s).
+;; 2012/08/31 dadams
+;; Do not bind bmkp-compilation-target-set(-all) unless defined.
+;; 2012/06/26 dadams
+;; Wrapped require of bookmark+-mac.el in eval-when-compile.
+;; 2012/06/21 dadams
+;; Try to load-library bookmark+-mac, for bmkp-menu-bar-make-toggle.
+;; 2012/02/26 dadams
+;; Bind:
+;; bmkp-this-file/buffer-bmenu-list to C-x p , not C-x p ..
+;; bmkp-(file|dired)-this-dir-jump* to C-x j . f|d not C-x j C-f|C-d.
+;; bmkp-file-this-dir-*-tags(-regexp)-jump* to C-x j t . [%][*+] not C-x j t C-f [%][*+].
+;; bmkp-this-buffer-jump* to C-x j , , not C-x j ..
+;; bmkp-autonamed-this-buffer-jump* to C-x j , # not C-x j # ..
+;; bmkp-autonamed-jump* to C-x j # not C-x j # #.
+;; bmkp-autofile-jump* in all Emacs versions.
+;; bmkp-find-file(-other-window), which is new, to C-x j C-f.
+;; new autofile tags jump commands bmkp-autofile-(all|some)-tags(-regexp)-jump* to
+;; C-x j t a [%][*+], which was for bmkp-find-file-*-tags*.
+;; bmkp-find-file-(all|some)-tags(-regexp)* to C-x j t C-f [%] [*+] not C-x j t a [%] [*+].
+;; Add to menus: bmkp-autofile-*. Rename menu items for bmkp-find-file: Find Autofile....
+;; Rename menu Bookmarked File to Find File or Autofile. For Emacs 20-21, make it a single item.
+;; bmkp-jump-tags-menu, bmkp-find-file-menu: Do not add Autofile tags items for Emacs 20.
+;; 2012/02/21 dadams
+;; Added bindings for: bmkp-autofile-(all|some)-tags(-regexp)-jump(-other-window),
+;; bmkp-find-file(-other-window) (was same as *autofile*).
+;; Changed bindings:
+;; *-this-dir*: . [df] (was C-d/C-f), *this-buffer*: , (was .), *find-file*tags*: C-f (was a).
+;; Define *autofile* for all Emacs versions. Separate bindings from *find-file* cmds.
+;; 2011/12/30 dadams
+;; Added aliases: bmkp-bookmark-(data|name)-from-record.
+;; Bind E to bmkp-edit-bookmark-record, not bmkp-edit-bookmark.
+;; Bind r to bmkp-edit-bookmark-name-and-file, not bookmark-rename. Ditto in menu.
+;; Use bmkp-get-bookmark-in-alist, not bookmark-get-bookmark in :visible conditions.
+;; menu-bar-bookmark-map: Added bmkp-edit-bookmark-record.
+;; bmkp-tags-menu: Added bmkp-edit-tags.
+;; 2011/12/14 dadams
+;; Removed conditions :enable bookmark-alist.
+;; 2011/12/09 dadams
+;; Commented out menu items with complex :enable conditions, replacing them with simple ones.
+;; Reason: too slow, especially in Emacs 20.
+;; 2011/12/05 dadams
+;; menu-bar-bookmark-map: Reordered items regarding bookmark files.
+;; 2011/12/03 dadams
+;; Bind C-x p L to bmkp-switch-bookmark-file-create, not bmkp-switch-bookmark-file.
+;; Reordered bookmark-file items in menu-bar-bookmark-map.
+;; 2011/11/18 dadams
+;; Bind bmkp-image-jump(-other-window) to C-x (4) j M-i.
+;; bmkp-jump-menu: Add bmkp-image-jump-other-window.
+;; 2011/11/15 dadams
+;; Bind *-this-file/buffer*, not *-this-buffer*.
+;; 2011/11/01 dadams
+;; Bind alias bmkp-autofile-jump(-*), not bmkp-find-file(-*) to C-x j a, so Icicles picks up key.
+;; Bind bmkp-bookmark-file-jump to C-x j y, not C-x j x. Bind bmkp-temporary-jump(-*) to C-x j x.
+;; bmkp-jump-menu: Bind bmkp-(autofile|temporary)-jump-other-window.
+;; 2011/10/31 dadams
+;; Bind bmkp-toggle-autotemp-on-set to C-x p x. Move bmkp-set-bookmark-file-bookmark to C-x p y.
+;; menu-bar-bookmark-map: Added: bmkp-toggle-autotemp-on-set.
+;; 2011/10/28 dadams
+;; menu-bar-bookmark-map:
+;; Added: bmkp-delete-all-temporary-bookmarks, bmkp-temporary-bookmarking-mode. Reordered.
+;; bmkp-options-menu: Added: bmkp-toggle-saving-menu-list-state, bmkp-toggle-saving-bookmark-file.
+;; 2011/04/24 dadams
+;; Added to Bookmarks menu and its Tags submenu: Purge Autofiles with No Tags.
+;; 2011/04/23 dadams
+;; bmkp-tags-menu:
+;; Added bmkp-set-tag-value, bmkp-(add|remove|copy)-tags, bmkp-paste-(add|replace)-tags.
+;; 2011/04/21 dadams
+;; Bound: bmkp-copy-tags, bmkp-paste-add-tags, bmkp-paste-replace-tags.
+;; 2011/04/16 dadams
+;; Added: bmkp-tags-map. Bound tag commands to prefix C-x p t.
+;; 2011/04/14 dadams
+;; Renamed menu Jump To Bookmark to just Jump To, in menu-bar-bookmark-map.
+;; 2011/04/13 dadams
+;; Added:
+;; bmkp-find-file-menu (bmkp-find-file(-(all|some)-tags(-regexp)(-other-window)),
+;; bmkp-jump-tags-menu (what was in main, plus bmkp-find-file-*-tags-regexp*),
+;; bmkp-tags-menu (list all, rename, remove from all, (un)tag a file).
+;; bmkp-jump(-other-window)-map:
+;; Added bmkp-find-file(-other-window) to menu.
+;; Bound keys for bmkp-find-file-(all|some)-tags(-regexp)(-other-window): C-x (4) j t a...
+;; 2011/04/02 dadams
+;; Added bindings for (new) bmkp-autofile-set,
+;; bmkp-file-this-dir-(all|some)-tags(-regexp)-jump(-other-window).
+;; 2011/04/01 dadams
+;; Added to bmkp-jump-menu: bmkp-(dired|file)-this-dir-jump-other-window.
+;; Created from code in bookmark+-1.el.
+
+;;;(@* "CHANGE LOG FOR `bookmark+-lit.el'")
+;;
+;; 2021/09/19 dadams
+;; Everywhere: Use bmkp-bmenu-buffer, not vanilla bookmark-bmenu-buffer.
+;; 2021/04/16 dadams
+;; bmkp-unlight-bookmark, bmkp-light-bookmarks, bmkp-cycle-lighted-this-buffer, bmkp-light-face,
+;; bmkp-light-style, bmkp-light-when, bmkp-lighting-attribute, bmkp-overlay-of-bookmark:
+;; Use bmkp-get-bookmark, not bookmark-get-bookmark, but in vanilla-compatible way.
+;; bmkp-bookmarks-lighted-at-point, bmkp-light-bookmark, bmkp-a-bookmark-lighted-on-this-line:
+;; Use bmkp-get-bookmark, not bookmark-get-bookmark.
+;; 2020/07/04 dadams
+;; Replaced string *Bookmark List* with bookmark-bmenu-buffer (for Emacs 28).
+;; 2020/01/12 dadams
+;; bmkp-lighted-jump-to-list: Raise error if no highlighted bookmarks at point.
+;; bmkp-(un)light-bookmark-this-buffer: Pass non-nil USE-NIL-ALIST-P to bookmark-completing-read.
+;; 2019/08/21 dadams
+;; bmkp-toggle-auto-light-when-(jump|set): Fix message: symbol-name, not symbol-value.
+;; 2019/05/01 dadams
+;; Added bmkp-lighted-jump-to-list.
+;; 2019/04/23 dadams
+;; Added bmkp-tooltip-content-function.
+;; bmkp-make/move-overlay-of-style: Use bmkp-tooltip-content-function.
+;; 2019/04/22 dadams
+;; Added bmkp-describe-bookmark-lighted-here.
+;; bmkp-make/move-overlay-of-style: Put bookmark description on overlay help-echo property.
+;; 2018/09/21 dadams
+;; Added: bmkp--pop-to-buffer-same-window. (Added also to bookmark+-bmu.el.)
+;; bmkp-lighted-jump: Use bmkp--pop-to-buffer-same-window, not switch-to-buffer.
+;; 2017/01/08 dadams
+;; Use the term "entry", not "property" everywhere, for bookmark entries (fields).
+;; 2016/10/25 dadams
+;; Added: Faces bmkp-light-autonamed-region, bmkp-light-non-autonamed-region.
+;; Options bmkp-light-style-autonamed-region, bmkp-light-style-non-autonamed-region.
+;; bmkp-light-styles-alist: Added Region style.
+;; bmkp-make/move-overlay-of-style:
+;; Added required arg BOOKMARK. Put overlay on region if region bookmark.
+;; bmkp-light-bookmark, bmkp-light-bookmarks:
+;; Include newly added bookmark arg in calls to bmkp-make/move-overlay-of-style.
+;; bmkp-light-face: Use face bmkp-light(-non)-autonamed-region for region bookmarks.
+;; bmkp-light-style: Use style bmkp-light-style(-non)-autonamed-region for region bookmarks.
+;; 2016/09/10 dadams
+;; bmkp-light-face, bmkp-light-style: Use bmkp-autonamed-bookmark-p.
+;; 2016/06/18 dadams
+;; Protected use of fringe-bitmaps with boundp (should not be necessary though).
+;; 2015/04/02 dadams
+;; eval-when-compile require of bookmark+-mac, for bmkp-define-show-only-command.
+;; 2015/02/08 dadams
+;; Renamed: bmkp-bmenu-show-only-lighted to bmkp-bmenu-show-only-lighted-bookmarks.
+;; bmkp-bmenu-show-only-lighted-bookmarks: Use macro bmkp-define-show-only-command to define it.
+;; 2014/07/06 dadams
+;; Added: bmkp-last-auto-light-when-jump, bmkp-last-auto-light-when-set,
+;; bmkp-toggle-auto-light-when-jump, bmkp-toggle-auto-light-when-set.
+;; 2013/06/09 dadams
+;; Added vacuous defvars to suppress free-var warnings.
+;; 2013/05/15 dadams
+;; Use bmkp-string-match-p instead of string-match wherever appropriate.
+;; 2012/10/09 dadams
+;; Made all autoload cookies explicitly load bookmark+.el(c). Should help ELPA (e.g. MELPA).
+;; 2012/09/22 dadams
+;; bmkp-light-bookmark(s): Put full bookmark, not name, on overlay as its bookmark property.
+;; bmkp-unlight-bookmark: Test using eq against full bookmark, not using equal against name.
+;; bmkp-a-bookmark-lighted-at-pos: overlay-get now returns full bookmark, so get name if needed.
+;; bmkp-overlay-of-bookmark: Use bookmark, not its name, like overlay-get does now. Test with eq.
+;; bmkp-light-bookmarks: Use add-to-list instead of unconditionally adding ov to ov-symb.
+;; 2012/04/28 dadams
+;; bmkp-make/move-overlay-of-style, bmkp-make/move-fringe: Use FRONT-ADVANCE arg for make-overlay.
+;; 2011/12/30 dadams
+;; Added aliases: bmkp-bookmark-(data|name)-from-record.
+;; bmkp-bookmarks-lighted-at-point: Include only bookmarks in bookmark-alist.
+;; bmkp-light-bookmark: Do nothing if BOOKMARK is not a bookmark or bookmark name.
+;; bmkp-a-bookmark-lighted-at-pos: Return nil if no bookmark (at POS) in bookmark-alist.
+;; 2011/11/15 dadams
+;; Applied renaming: bmkp-this-buffer-cycle-sort-comparer to *-this-file/buffer*.
+;; 2011/08/09 dadams
+;; Bind icicle-unpropertize-completion-result-flag to t for all calls to completing-read.
+;; 2011/04/12
+;; bmkp-cycle-lighted-this-buffer: Use bmkp-sort-omit, not bmkp-sort-and-remove-dups.
+;; 2011/04/01 dadams
+;; bmkp-light-bookmark(s): Don't call bookmark-handle-bookmark. Wrap with with-current-buffer.
+;; 2011/01/03 dadams
+;; Added autoload cookies: defcustoms and commands.
+;; 2010/12/10 dadams
+;; Added defalias for bookmark-name-from(-full)-record, to fix gratuitous Emacs name change.
+;; 2010/09/25 dadams
+;; Added: bmkp-set-lighting-for(bookmarks|(-this)-buffer). Requested by Joe Bloggs.
+;; bmkp-set-lighting-for-bookmark: Added LIGHT-NOW-P arg (from prefix arg).
+;; 2010/09/11 dadams
+;; Removed eval-when-compile for bookmark+-bmu, bookmark+-1.
+;; 2010/08/15 dadams
+;; Require: bookmark.el.
+;; Require when compile: bookmark+-bmu.el, bookmark+-1.el, pp+.el (soft).
+;; Applied renaming of bmkp-barf-if-not-in-menu-list to bmkp-bmenu-barf-if-not-in-menu-list.
+;; bmkp-light-bookmark(s): Added missing arg to throw call.
+;; bmkp-light-bookmarks: Use bmkp-remove-if, not remove-if.
+;; bmkp-light-bookmarks-in-region, bmkp-light-non-autonamed-this-buffer:
+;; Use bmkp-remove-if-not, not remove-if-not.
+;; bmkp-read-set-lighting-args: Use pp-read-expression-map only if bound (pp+.el).
+;; 2010/07/03 dadams
+;; bmkp-set-lighting-for-bookmark, bmkp-bmenu-set-lighting-for-marked:
+;; Use *-refresh-menu-list, not *-surreptitiously-*.
+;; 2010/07/01 dadams
+;; Created.
+
+;;;(@* "CHANGE LOG FOR `bookmark+-mac.el'")
+;;
+;; **************************************************************************************************
+;; NOTE: If you byte-compile Bookmark+ (recommended), then WHENEVER `bookmark+-mac.el' is updated,
+;; you must load `bookmark+-mac.el' (not just `bookmark+-mac.elc'), then compile it, then
+;; RECOMPILE *ALL* of the other Bookmark+ source files as well. This is normal for Lisp: code
+;; that depends on macros needs to be byte-compiled anew after loading the updated macros.
+;; **************************************************************************************************
+;;
+;; 2021/04/16 dadams
+;; bmkp-define-file-sort-predicate: Use bmkp-get-bookmark, not bookmark-get-bookmark.
+;; 2021/03/04 dadams
+;; Removed autoload cookie for bmkp-types-alist. Its def is also in bookmark+-1.el now.
+;; 2020/11/28 dadams
+;; Added: bmkp-define-history-variables, funtion bmkp-types-alist.
+;; 2017/03/31 dadams
+;; bmkp-define-next+prev-cycle-commands: Added optional arg OTHERP.
+;; 2015/04/03 dadams
+;; bmkp-replace-regexp-in-string: Copied defn here - used to produce the macro code for
+;; bmkp-define-show-only-command and bmkp-define-sort-command.
+;; 2015/02/22 dadams
+;; bmkp-menu-bar-make-toggle: Corrected doc string - just start with HELP.
+;; 2015/02/08 dadams
+;; Added: bmkp-define-show-only-command.
+;; 2014/07/11 dadams
+;; bmkp-define-sort-command: Use setq, not push, for Emacs 20.
+;; 2014/07/06 dadams
+;; bmkp-menu-bar-make-toggle: Redefined - no longer use menu-bar-make-toggle. Support keywords.
+;; 2014/05/27 dadams
+;; Added: bmkp-with-help-window.
+;; 2013/04/26 dadams
+;; Added: bmkp-with-bookmark-dir. (Not used currently. For user code.)
+;; 2012/10/09 dadams
+;; Made all autoload cookies explicitly load bookmark+.el(c). Should help ELPA (e.g. MELPA).
+;; 2012/06/26 dadams
+;; Moved bmkp-assoc-delete-all, bmkp-replace-regexp-in-string to bookmark+-bmu.el.
+;; 2012/04/27
+;; Added: bmkp-with-output-to-plain-temp-buffer.
+;; 2012/04/12 dadams
+;; bmkp-define-sort-command: Do not bmkp-bmenu-goto-bookmark-named unless current-bmk (play safe).
+;; 2012/04/11 dadams
+;; bmkp-define-sort-command: In function def, change order to: fn, reverse-fn, unsorted.
+;; 2011/12/30 dadams
+;; bmkp-define-cycle-command: Applied renaming of bmkp-sort-and-remove-dups to bmkp-sort-omit.
+;; bmkp-define-file-sort-predicate: Updated doc string of generated functions.
+;; Added renamings of bookmark-name-from(-full)-record, bookmark-get-bookmark-record.
+;; 2011/04/12
+;; bmkp-define-cycle-command: Use bmkp-sort-omit, not bmkp-sort-and-remove-dups.
+;; 2011/01/03 dadams
+;; Added autoload cookies: defmacro.
+;; 2010/09/25 dadams
+;; Added: bmkp-define-next+prev-cycle-commands.
+;; 2010/09/24 dadams
+;; Added: bmkp-define-cycle-command.
+;; 2010/08/18 dadams
+;; Removed eval-when-compile for bookmark+-(bmu|1).el.
+;; 2010/08/15 dadams
+;; Created, from code in other Bookmark+ files.
+
+;;;(@* "CHANGE LOG FOR `bookmark+.el'")
+;;
+;; 2021/09/19 dadams
+;; Version 2021.09.19
+;; Added option bmkp-bmenu-buffer.
+;; Autoload bookmark-bmenu-buffer.
+;; Moved defgroup here, from bookmark+-bmu.el. Added autoload cookie.
+;; 2021/04/18 dadams
+;; Version 2021.04.18
+;; 2021/03/04 dadams
+;; Version 2021.03.04
+;; 2021/02/12 dadams
+;; Version 2021.02.12
+;; 2020/07/04 dadams
+;; Version 2020.07.04
+;; Added defconst for bookmark-bmenu-buffer (Emacs 28).
+;; Added defvar, make-variable-buffer-local declaration for bookmark-annotation-name (Emacs 28).
+;; 2020/07/03 dadams
+;; Version 2020.07.03
+;; 2020/01/22 dadams
+;; Version 2020.01.22
+;; 2020/01/12 dadams
+;; Version 2020.01.12
+;; 2019/04/22 dadams
+;; Version 2019.04.22
+;; 2019/04/22 dadams
+;; Version 2019.02.18
+;; 2018/10/17 dadams
+;; Version 2018.10.17.
+;; 2018/09/21 dadams
+;; Version 2017.09.21.
+;; 2017/03/31 dadams
+;; Version 2017.03.31. Fixed cycling bookmarks across buffers. Added other-window cycling cmds.
+;; 2017/02/26 dadams
+;; Version 2017.02.26. Added auto-bookmarking for Info. Better EWW - thx to Charles Roelli.
+;; 2016/11/14 dadams
+;; Version 2016.11.14. Added support for EWW bookmarks. Thx to Charles Roelli.
+;; 2015/02/22 dadams
+;; Version 2015.02.22.
+;; 2015/02/08 dadams
+;; Version 2015.02.08
+;; 2015/01/04 dadams
+;; Version 2015.01.04.
+;; 2013/04/14 dadams
+;; Added Version entry to header. Updated bmkp-version-number to the same thing.
+;; 2012/10/09 dadams
+;; Made all autoload cookies explicitly load bookmark+.el(c). Should help ELPA (e.g. MELPA).
+;; 2012/06/26 dadams
+;; Wrapped require of bookmark+-mac.el in eval-when-compile.
+;; 2012/06/21 dadams
+;; Try to load-library bookmark+-mac. Require it only if cannot load-library.
+;; 2012/02/26 dadams
+;; Version 3.4.0.
+;; 2011/12/30 dadams
+;; Version 3.3.0.
+;; 2011/04/12 dadams
+;; Version 3.2.2.
+;; 2011/04/01 dadams
+;; Require bookmark+-key.el (new). Version 3.2.1.
+;; 2011/01/03 dadams
+;; Added autoload cookies: defconst, command.
+;; 2010/08/19
+;; bmkp-version-number: Version 3.2.0.
+;; 2010/08/15 dadams
+;; Require bookmark+-mac.el.
+;; Do not ensure loaded before compile (not needed here now).
+;; 2010/07/14 dadams
+;; Version 3.1.1.
+;; Moved main content of bookmark+.el to new files bookmark+-1.el and bookmark+-bmu.el.
+;; 2010/07/13 dadams
+;; Version 3.1.0.
+;; Added redefinitions: bookmark-bmenu-(1|2)-window, bookmark-bmenu-other-window-with-mouse,
+;; bookmark-bmenu-this-window, bookmark-bmenu-switch-other-window.
+;; Added: bmkp-last-bookmark-file, bmkp-switch-to-last-bookmark-file.
+;; Removed pre-23 version of bookmark-bmenu-switch-other-window.
+;; bookmark-load: Use bmkp-last-bookmark-file when read file name. Added missing prefix arg.
+;; Save old current as bmkp-last-bookmark-file.
+;; bookmark-bmenu-list: If bookmark file has changed do not restore state saved from other file.
+;; Save old current as bmkp-last-bookmark-file.
+;; bmkp-bmenu-list-1: Do not use bmkp-bmenu-title if it is empty ("").
+;; bookmark-bmenu-mode: Added to doc string: bmkp-switch-bookmark-file.
+;; bookmark-bmenu-other-window: Do not bind bookmark-automatically-show-annotations (per vanilla).
+;; bookmark-bmenu-show-annotation: Ensure in bmenu list and on a bookmark line.
+;; bmkp-switch-bookmark-file: Use bmkp-last-bookmark-file when read file name.
+;; bmkp-bmenu-define-full-snapshot-command: Set bmkp-last-bookmark-file.
+;; bmkp-bookmark-description: Fixed typo: bmkp-bookmark-file-bookmark-p (not desktop).
+;; bmkp-make-bookmark-file-record: Use arg file (not bmkp-non-file-filename) as filename entry.
+;;
+;; Added more autoload cookies.
+;; 2010/07/09 dadams
+;; Added: bmkp-bmenu-mark-bookmark-file-bookmarks, bmkp-bmenu-show-only-bookmark-files,
+;; bmkp-bookmark-file-jump, bmkp-set-bookmark-file-bookmark, bmkp-bookmark-file-history,
+;; bmkp-use-bookmark-file-create, bmkp-bookmark-file, bmkp-bookmark-file-alist-only,
+;; bmkp-bookmark-file-bookmark-p, bmkp-jump-bookmark-file, bmkp-make-bookmark-file-record.
+;; bmkp-types-alist, bmkp-buffer-names, bmkp-bmenu-mode-status-help, bmkp-bmenu-propertize-item,
+;; bmkp-this-buffer-p, bmkp-last-specific-buffer-p, bmkp-specific-buffers-alist-only,
+;; bmkp-bookmark-description, bookmark-bmenu-mode: Updated for bookmark-file bookmarks.
+;; bookmark--jump-via: Added a catch, so a handler can skip all other processing when it's done.
+;; bookmark-load: Final msg says whether overwritten.
+;; Bound and added to menus: bmkp-set-bookmark-file-bookmark,
+;; bmkp-bmenu-mark-bookmark-file-bookmarks,
+;; bmkp-bmenu-show-only-bookmark-files, bmkp-bookmark-file-jump.
+;; 2010/07/07 dadams
+;; bookmark-handle-bookmark: Bind use-dialog-box, use-file-dialog to nil.
+;; bookmark-location: From Emacs 23: Use location property and -- Unknown location --.
+;; bmkp-switch-bookmark-file: Bind insert-default-directory to nil.
+;; bmkp-empty-file: Expand FILE. Return FILE.
+;; 2010/07/03 dadams
+;; Added: bmkp-bmenu-describe-marked, bmkp-bookmark-description.
+;; bmkp-describe-bookmark: Rewrote to use bmkp-bookmark-description.
+;; Bound bmkp-bmenu-describe-marked to C-h >.
+;; bmkp-bmenu-menubar-menu: Added bmkp-bmenu-describe-(marked|bookmark).
+;; Updated doc string of bookmark-alist.
+;; 2010/07/01 dadams
+;; Added: bmkp-bmenu-mark-lighted-bookmarks, bmkp-bmenu-set-tag-value-for-marked,
+;; bmkp-bmenu-show-only-tagged, bmkp-occur-create-autonamed-bookmarks,
+;; bmkp-set-autonamed-bookmark, bmkp-set-autonamed-bookmark-at-line,
+;; bmkp-set-autonamed-regexp-buffer, bmkp-set-autonamed-regexp-region,
+;; bmkp-set-tag-value-for-navlist, bmkp-prompt-for-tags-flag, bmkp-menu-bar-make-toggle,
+;; bmkp-same-creation-time-p, bmkp-set-tag-value-for-bookmarks,
+;; bmkp(-bmenu)-highlight-menu, bmkp-options-menu.
+;; Renamed: bmkp-use-region-flag to bmkp-use-region,
+;; bmkp-bmenu-jump-menu to bmkp-jump-menu.
+;; Removed: bmkp-cycle-this-buffer-buff (unused).
+;; Soft-require new library bookmark+-lit.el.
+;; Split off new file bookmark+-chg.el from bookmark+-doc.el.
+;; Changed default values of faces bmkp->-mark, bmkp-t-mark.
+;; bmkp-crosshairs-flag: Added :set instead of add-hook at top level.
+;; bmkp-use-region: Changed from boolean to choice - added cycling-too value.
+;; bookmark-set: Added INTERACTIVEP arg. Prompt for tags when bmkp-prompt-for-tags-flag.
+;; Auto-highlight when set, per bmkp-auto-light-when-set.
+;; bookmark--jump-via: Auto-highlight when jump, per bmkp-auto-light-when-jump.
+;; Set BOOKMARK to result of bmkp-update-autonamed-bookmark.
+;; Bind orig-buff when running hook.
+;; bookmark-default-handler: Pass the bookmark too as an arg to bmkp-goto-position.
+;; bookmark-relocate, bookmark-rename, bmkp-bmenu-list-1, bmkp-remove(-all)-tags, bmkp-add-tags:
+;; Add 0 as FRAME arg to get-buffer-window.
+;; bookmark-delete: Remove any highlighting on bookmark.
+;; bmkp-bmenu-list-1: Add highlight-overrides indicator.
+;; bmkp-completing-read-1: Added (not laxp) guard for first branch of main if.
+;; bmkp-crosshairs-highlight: Assign a priority. Make the cmd a no-op for Emacs 20-21.
+;; bmkp-choose-navlist-*, bmkp-navlist-bmenu-list, bmkp-jump-in-navlist*,
+;; bmkp-cycle(-this-buffer*):
+;; Set bmkp-current-nav-bookmark to bookmark, not to its name.
+;; bmkp-update-autonamed-bookmark: Do not set bmkp-current-nav-bookmark to the name.
+;; Call bmkp-refresh-menu-list even if menu list is not displayed.
+;; Pass the bookmark name to bmkp-refresh-menu-list.
+;; Return the updated BOOKMARK.
+;; bmkp-refresh-menu-list: Set window point also.
+;; bmkp-goto-position:
+;; Added BOOKMARK arg. When bmkp-save-new-location-flag, update BOOKMARK. Return indicator.
+;; bmkp-create-varlist-bookmark: Call bookmark-set with INTERACTIVEP arg.
+;; bmkp-cycle(-this-buffer*): Added STARTOVERP arg. Pass OTHER-WINDOW, STARTOVERP to bmkp-cycle-1.
+;; bmkp-cycle-1: Added STARTOVERP arg. If non-nil pop-up-frames, then inhibit showing annotation.
+;; Use region only if bmkp-use-region value is cycling-too.
+;; Use eq for *-list-position test. If *-list-position returns nil, then reset.
+;; Use save-selected-window, unlesl OTHER-WINDOW.
+;; bmkp-(next|previous)-bookmark(-this-buffer|-w32): Added STARTOVERP arg. C-u: start over at 1.
+;; Bind highlight cmds: *-map: h,H,u,U,C-u,=,C-up|down. *-bmenu-*map: H+,H>+,H>H,HH,HS,H>U,HU.
+;; *-jump-map: h. Bind TS in *-bmenu-*map.
+;; Add bmkp-occur-create-autonamed-bookmarks to occur-mode-map as C-c b.
+;; Menus: Added Highlight, Toggle Option. Added light to Jump To, Show, Mark, mouse. Reorder.
+;; 2010/06/23 dadams
+;; Split the change log off from file bookmark+-doc.el to new file bookmark+-chg.el.
+;; 2010/06/21 dadams
+;; Renamed: bmkp-toggle-autoname-bookmark-set/delete to bmkp-toggle-autonamed-bookmark-set/delete,
+;; bmkp-autonamed-bookmarks-alist-only to bmkp-autonamed-this-buffer-alist-only,
+;; bmkp-bookmark-autoname-p to bmkp-autonamed-bookmark-for-buffer-p,
+;; Added: bmkp-autonamed-alist-only, bmkp-non-autonamed-alist-only, bmkp-autonamed-bookmark-p,
+;; bmkp-completing-read-1: Use DEFAULT as default. Use just (not lax) - no non-t.
+;; Use DEFAULT if empty input only if DEFAULT is non-nil.
+;; bmkp-choose-navlist-of-type: Added pseudo-type "any".
+;; bmkp-specific-buffers-alist-only: Exclude desktop etc. bookmarks.
+;; bmkp-update-autonamed-bookmark: Arg can be a bookmark (not just name).
+;; 2010/06/19 dadams
+;; RENAMED bookmarkp* TO bmkp*. ***** THIS IS AN INCOMPATIBLE CHANGE ******
+;;
+;; If you have existing customizations, or if you have bookmarks that have the (internal) tag
+;; "bmkp-jump", then YOU MUST REPLACE occurrences of "bookmarkp" by "bmkp" EVERYWHERE. This
+;; includes replacing occurrences in (1) your bookmarks file (bookmark-default-file), (2) your
+;; state file (bmkp-bmenu-state-file), and (3) your command file (bmkp-bmenu-commands-file).
+;;
+;; Changed *-bmenu-w32-open-select binding to M-o from M-v.
+;; 2010/06/11 dadams
+;; Wrap all (require '* nil t) in condition-case.
+;; 2010/06/07 dadams
+;; Fix deskstop bookmarks for Emacs < 22. Protect:
+;; *-release-lock with fboundp, *-buffer-args-list with boundp, *-dir with Emacs version #,
+;; 2010/05/30 dadams
+;; Added: bookmarkp-(next|previous)-bookmark-w32(-repeat). Bound to C-x p (next|prior).
+;; 2010/05/29 dadams
+;; *-bmenu-list, *-choose-navlist-from-bookmark-list, *-bmenu-define(-full-snapshot)-command,
+;; *-save-menu-list-state, -make-bookmark-list-record:
+;; Add/restore bookmarkp-bmenu-filter-pattern to/from state.
+;; *-jump-bookmark-list: Set bookmarkp-latest-bookmark-alist to bookmark-alist.
+;; Reordered Bookmark menu and added items:
+;; Set Bookmark, Delete Autonamed Bookmark, Delete All Autonamed Bookmarks Here,
+;; Delete Bookmarks Here, Delete Bookmark, Rename Bookmark, Bookmark List for This Buffer,
+;; Bookmark List for Navlist, Set Navlist to Bookmarks of Type,
+;; Set Navlist from Bookmark-List Bookmark, Insert Bookmark Contents, Insert Bookmark Location.
+;; Added to Bookmark+ menu: Set Navlist *.
+;; Added to bookmarkp-bmenu-jump-menu: In Navigation List.
+;; Added :enable entries for menu items.
+;; Updated bookmark-bmenu-mode doc string for cycling, navlist, and options.
+;; Corrected bindings of bookmarkp-jump-in-navlist(-other-window).
+;; 2010/05/26 dadams
+;; Added:
+;; bookmarkp-choose-navlist-(from-bookmark-list|of-type), bookmarkp-crosshairs-highlight,
+;; bookmarkp-cycle(-this-buffer)(-other-window), bookmarkp-delete-bookmarks,
+;; bookmarkp-jump-in-navlist(-other-window), bookmarkp-navlist-bmenu-list,
+;; bookmarkp-(next|previous)-bookmark(-this-buffer)(-repeat),
+;; bookmarkp-toggle-autoname-bookmark-set/delete, bookmarkp-autoname-bookmark(-function),
+;; bookmarkp-autonamed-bookmarks-alist-only, bookmarkp-autoname-format,
+;; bookmarkp-bookmark-autoname-p, bookmarkp-crosshairs-flag,
+;; bookmarkp-this-buffer-cycle-sort-comparer, bookmarkp-current-bookmark-list-state,
+;; bookmarkp-cycle-1, bookmarkp-list-position, bookmarkp-position-cp,
+;; bookmarkp-current-nav-bookmark, bookmarkp-cycle-this-buffer-buff, bookmarkp-nav-alist,
+;; bookmarkp-update-autonamed-bookmark, bookmarkp-delete-all-autonamed-for-this-buffer.
+;; Bound:
+;; bookmarkp-choose-navlist-from-bookmark-list, bookmark-insert-location,
+;; bookmarkp-navlist-bmenu-list, bookmarkp-choose-navlist-of-type, bookmarkp-delete-bookmarks,
+;; bookmarkp-toggle-autoname-bookmark-set/delete, bookmarkp-jump-in-navlist(-other-window),
+;; bookmarkp-(next|previous)-bookmark(-this-buffer)-repeat.
+;; bookmark--jump-via: Update the name and position of an autonamed bookmark.
+;; 2010/05/22 dadams
+;; *-this-buffer-p: Return nil for bookmarks not really associated with a buffer.
+;; *-default-handler, *-goto-position: Forgot comma to eval file-name when no-such-file error.
+;; *-show-annotation: Bind buffer-read-only to nil for updating.
+;; 2010/05/19 dadams
+;; Added: bookmarkp-this-buffer-bmenu-list. Bound to `C-x p .'.
+;; menu-bar-bookmark-map:
+;; Added bookmarkp-this-buffer-bmenu-list. Added separators.
+;; Added vanilla items edit, write, load, to impose order. Renamed item edit.
+;; 2010/05/16 dadams
+;; bookmark-set: Quoted history arg. Thx to S. Nemec.
+;; bookmarkp-bmenu-define-full-snapshot-command: Use quote comma, not quote, for *-specific-*.
+;; 2010/05/15 dadams
+;; Replace *same-(buffer|file)-jump* by *specific-(buffers|files)-jump*: read multiple buff/files.
+;; Renamed: *same-(buffer|file)* to *-last-specific-(buffer|file)* for pred, alist, and var.
+;; Renamed: *same-(buffer|file)* to *specific-(buffer|file)* for hist, *types*, mark/show cmds.
+;; Renamed: *-selected-buffers-alist* to *-specific-buffers-alist*.
+;; Added: *-specific-files-alist*, *-(all|some)-tags(-regexp)-alist-only.
+;; *-completing-read-(buffer|file)-name: Use (buffer|file)-name-history, not *-same-*-history.
+;; *-read-tags-completing: Rewrote to correctly handle cons and string tags, error handling, etc.
+;; *-bmenu-(add|remove)-tags-*-marked: Error handling.
+;; *(all|some)-tags(-regexp)-jump*: Use *-(all|some)-tags(-regexp)-alist-only.
+;; 2010/05/11 dadams
+;; Added: bookmarkp-bmenu-mark-same-(buffer|file)-bookmarks, bookmarkp-this-(buffer|file)-p,
+;; bookmarkp-this-(buffer|file)-alist-only, bookmarkp-bmenu-show-only-same-(buffer|file),
+;; bookmarkp-completing-read-(buffer|file)-name, bookmarkp-same-(buffer|file)-history,
+;; bookmarkp-(same|this)-(buffer|file)-alist-only, bookmarkp-last-same-(buffer|file),
+;; bookmarkp-(same|this)-(buffer|file)-jump(-other-window), bookmarkp-(buffer|file)-names,
+;; bookmarkp-same-(buffer|file)-as-last-p, bookmarkp-other-window-pop-to-flag,
+;; bookmarkp-select-buffer-other-window.
+;; Use bookmarkp-select-buffer-other-window instead of switch-to-buffer-other-window everywhere.
+;; Bound = (b|f) (M|S), C-x j (=|.) (b|f) to (same|current)-(buffer|file) commands.
+;; *-types-alist: Handle same-(buffer|file) too.
+;; *-bmenu-list, *-bmenu-define-full-snapshot-command, *-save-menu-list-state:
+;; Handle bookmarkp-last-same-(buffer|file) as part of state.
+;; 2010/05/05 dadams
+;; bookmarkp-create-varlist-bookmark, bookmarkp-make-varlist-record:
+;; Added optional arg BUFFER-NAME.
+;; bookmark-alist: Corrected doc string wrt BUFFER-NAME and region context strings.
+;; 2010/05/04 dadams
+;; Added: bookmarkp-create-varlist-bookmark.
+;; bookmarkp-jump-varlist: If bookmark's buffer doesn't exist, use current buffer and show msg.
+;; 2010/04/24 adams
+;; Added: bookmarkp-bmenu-show-only-varlists, bookmarkp-set-restrictions-bookmark,
+;; bookmarkp-set-varlist-bookmark, bookmarkp-varlist-jump, bookmarkp-varlist,
+;; bookmarkp-jump-varlist, bookmarkp-make-varlist-record, bookmarkp-printable-p,
+;; bookmarkp-printable-vars+vals, bookmarkp-read-variables-completing,
+;; bookmarkp-read-variable, bookmarkp-varlist-alist-only, bookmarkp-varlist-bookmark-p,
+;; bookmarkp-varlist-history.
+;; Bound bookmarkp-bmenu-show-only-varlists to V S, bookmarkp-varlist-jump to C-x j v (and menu).
+;; *-types-alist: Added bookmarkp-varlist-history.
+;; *-bmenu-mode-status-help, *-bmenu-propertize-item, *-describe-bookmark: Handle varlist bmks.
+;; *-bmenu-w32-open-select: Changed binding to M-v from V.
+;; *-bmenu-mode: Updated doc string.
+;; 2010/04/17 dadams
+;; bookmark-set: Numeric prefix arg means use all bookmarks as completion candidates.
+;; Simplified the prompt.
+;; bookmarkp-completing-read-1:
+;; Use icicle-transform-multi-completion in icicle-delete-candidate-object
+;; Ensure loaded before byte-compile (put a require after provide).
+;; Move bookmarkp-replace-regexp-in-string before macro bookmarkp-define-sort-command (uses it).
+;; bookmarkp-bmenu-w32-open-with-mouse, bookmarkp-bmenu-mouse-3-menu:
+;; Use with-current-buffer, not save-excursion of set-buffer.
+;; bookmarkp-make-dired-record, bookmarkp-jump-dired: Use dolist, not mapcar (just side effect).
+;; bookmarkp-(some|all)-tags-jump(-other-window): Removed extraneous arg in error call.
+;; 2010/04/16 dadams
+;; Added: bookmarkp-completing-read-1, bookmarkp-completing-read-lax,
+;; bookmarkp-selected-buffers-alist-only.
+;; bookmark-set: Use bookmark-completing-read-lax w/ buffer's bookmarks, not read-from-minibuffer.
+;; bookmark-completing-read: Define using bookmarkp-completing-read-1.
+;; 2010/04/09 dadams
+;; bookmarkp-edit-bookmark: Update dired-directory property along with filename property.
+;; 2010/03/28 dadams
+;; bookmarkp-goto-position: Don't funcall bookmarkp-jump-display-function if it is nil.
+;; 2010/03/28 dadams
+;; bookmark-default-handler: Don't funcall bookmarkp-jump-display-function if it is nil.
+;; 2010/03/27 dadams
+;; Changed the customization group from bookmarkp to bookmark-plus.
+;; Moved doc and change history from bookmark+.el to this new file, bookmark+-doc.el.
+;; bookmarkp-commentary-button: Use bookmark+-doc.el, not bookmark+.el.
+;; 2010/03/17 dadams
+;; Added: bookmarkp-toggle-bookmark-set-refreshes, bookmarkp-refresh-latest-bookmark-list,
+;; bookmarkp-after-set-hook.
+;; 2010/03/16 dadams
+;; Fixed parens placement (typo) for last change to define *-jump-woman for Emacs 20.
+;; 2010/03/11 dadams
+;; Define bookmarkp-jump-woman also for Emacs 20 (just raise an error).
+;; *-show-annotation: Typo: bookmark -> bmk-name.
+;; 2010/03/10 dadams
+;; Added: bookmarkp-bookmark-creation-cp, bookmarkp-bmenu-sort-by-creation-time (bind: s0, menu).
+;; *-make-record-default: Add entry: created.
+;; *-describe-bookmark: Add creation time to description.
+;; 2010/03/03 dadams
+;; *-sort-and-remove-dups: Do not set bookmarkp-sorted-alist to the result.
+;; *-bmenu-list-1: Set bookmarkp-sorted-alist to the result of calling *-sort-and-remove-dups.
+;; 2010/03/02 dadams
+;; Added: bookmarkp-sorted-alist.
+;; *-bmenu-list-1: Use bookmarkp-sorted-alist.
+;; *-sort-and-remove-dups: Set bookmarkp-sorted-alist to the result.
+;; All *-cp (and hence *-define-file-sort-predicate):
+;; Accept bookmark names as args, in addition to bookmarks.
+;; bookmark-alpha-p: Don't use bookmarkp-make-plain-predicate, to avoid infinite recursion.
+;; 2010/02/28 dadams
+;; Added: bookmarkp-send-bug-report.
+;; bookmarkp-bmenu-mode-status-help: Rewrote to provide only Bookmark+ help. Added help buttons.
+;; Fixed Commentary typos.
+;; 2010/02/26 dadams
+;; Added: bookmarkp-desktop-change-dir, bookmarkp-desktop-kill, bookmarkp-desktop-delete.
+;; *-jump-desktop: Call *-desktop-change-dir.
+;; *-read-bookmark-for-type: Added optional arg ACTION.
+;; 2010/02/24 dadams
+;; *-bmenu-list: Handle case null last-bookmark-file (due to old file format). Thx to Seb Luque.
+;; *-make-record-default: protect dired-buffers with boundp. Thx to Janek Schwarz.
+;; 2010/02/16 dadams
+;; bookmarkp-define-sort-command: Add msg suffix about repeating.
+;; bookmarkp-msg-about-sort-order: Added optional arg SUFFIX-MSG.
+;; 2010/02/15 dadams
+;; Added: bookmark-bmenu-switch-other-window (redefinition for Emacs 20-22).
+;; *-bmenu-mode: Added redefinition, instead of advising.
+;; *-send-edited-annotation, *-relocate, *-rename, *-bmenu-refresh-menu-list,
+;; *-remove(-all)-tags, *-add-tags:
+;; Refresh the menu list, to pick up changes.
+;; *-refresh-menu-list: Added optional arg BOOKMARK: go to it.
+;; Do not bind bookmark-bmenu-relocate unless it's defined.
+;; *-handler-cp: Respect case-fold-search.
+;; 2010/02/14 dadams
+;; Renamed bookmark-bmenu-list-1 to bookmarkp-bmenu-list-1.
+;; Added faces: bookmarkp-(a|t|>|D)-mark, bookmarkp-heading (don't use bookmark-menu-heading).
+;; Added redefinitions: bookmark-send-edited-annotation, bookmark(-bmenu)-show-annotation,
+;; bookmark-show-all-annotations.
+;; *-bmenu-mark, *-bmenu-delete, *-bmenu-list-1: Add faces to marks.
+;; *-bmenu-list-1 and everywhere: Get rid of "% " before menu-list title.
+;; *-bmenu-list-1: Use "a", not "*", as annotation mark.
+;; Add "t" mark for tags. Add an extra space before bookmark name.
+;; *-bmenu-marks-width: change value from 2 to 4, for the tags column and the extra space.
+;; 2010/02/13 dadams
+;; Added: bookmarkp-desktop-history,
+;; bookmarkp-desktop-jump (bound to C-x j K; added to menu),
+;; bookmarkp-bookmark-list-jump (bound to C-x j B; added to menu),
+;; bookmarkp-bookmark-list-alist-only, bookmarkp-bookmark-list-history.
+;; *-types-alist: Added entries for desktops and bookmark-lists.
+;; *-describe-bookmark: Added optional arg, to show full (internal) info.
+;; Bind it to ? in bookmark-map.
+;; *-jump-bookmark-list: Pop to the bookmark-list (to show it).
+;; *-bmenu-mark-w3m-bookmarks: Typo: wrong predicate.
+;; *(-bmenu)-remove-all-tags: Raise error if no tags to remove.
+;; *-bmenu-remove-all-tags: Require confirmation if interactive.
+;; *-bmenu-remove-tags: Added optional arg MSGP.
+;; Menus: Added "..." as needed.
+;; *-bmenu-mouse-3-menu: Guard bookmark-bmenu-relocate with fboundp.
+;; 2010/02/12 dadams
+;; Added: bookmarkp-bmenu-define-jump-marked-command. Bound to M-c and added to menu.
+;; Changed bookmarkp-toggle-saving-bookmark-file binding to M-~ (M-s conflicts w isearch-multi).
+;; Updated bookmark-bmenu-mode doc string.
+;; 2010/02/11 dadams
+;; Added: bookmarkp-types-alist,
+;; bookmarkp-(dired|gnus|info|man|region|w3m|(non-|local-|remote-)file)-history.
+;; bookmark-completing-read: Added optional HIST arg.
+;; *-(relocate|rename|insert(-location)): Added bookmark default for interactive use.
+;; *-jump-dired: Handle bookmarkp-jump-display-function.
+;; *-read-bookmark-for-type: Added optional HIST arg.
+;; *-jump-to-type(-other-window),
+;; *-(dired|file|gnus|info|man|region|w3m|(local-|non-|remote-)file)-jump*(-other-window):
+;; Use type-specific history var.
+;; 2010/02/09 dadams
+;; Added: bookmarkp-get-tag-value.
+;; bookmark--jump-via: Handle special bookmark tag bookmarkp-jump.
+;; 2010/02/08 dadams
+;; Renamed: bookmarkp-bmenu-dired-marked-local to bookmarkp-bmenu-dired-marked.
+;; bookmarkp-bmenu-dired-marked: Handle remote bookmarks if Emacs > 23.1.
+;; Support tags with values.
+;; Added: bookmarkp-tag-name, bookmarkp-full-tag, bookmarkp(-bmenu)-set-tag-value.
+;; Renamed variable (not fn) bookmarkp-tags-list to bookmarkp-tags-alist.
+;; Use bookmarkp-full-tag everywhere for tag completion.
+;; *-has-tag-p: Use assoc-default, not member.
+;; *-read-tag(s)-completing: CANDIDATE-TAGS is now an alist.
+;; *-list-all-tags: Added optional arg FULLP (prefix arg).
+;; *-tags-list: Added optional arg NAMES-ONLY-P.
+;; *-(add|remove|rename)-tags: Use copy-alist, not copy-sequence. Alist, not list, membership.
+;; *-rename-tag: Raise error if no tag with old name.
+;; *-bmenu-mark-bookmarks-tagged-regexp, *-regexp-filtered-tags-alist-only, *-describe-bookmark,
+;; *-(all|some)-tags-regexp-jump(-other-window):
+;; Use bookmarkp-tag-name.
+;; *-bmenu-mark/unmark-bookmarks-tagged-(all|some)/(none|not-all), *-define-tags-sort-command:
+;; Use assoc-default, not member.
+;; Added: bookmarkp-bmenu-add-tags, bookmarkp-bmenu-remove(-all)-tags.
+;; *-bmenu-mouse-3-menu: Use bookmarkp-bmenu-add-tags, bookmarkp-bmenu-remove(-all)-tags.
+;; Added bookmarkp-bmenu-set-tag-value.
+;; *-bmenu-mark-bookmarks-satisfying: Made it a command (interactive).
+;; 2010/02/07 dadams
+;; *-write-file: Corrected handling of ALT-MSG.
+;; Cleanup.
+;; *-remove-tags: Don't call *-get-tags twice.
+;; *-bmenu-(un)mark-bookmarks-tagged(-not)-(all|none|some):
+;; Don't duplicate what bookmarkp-read-tags-completing does.
+;; *-add-tags, *-remove-tags(-from-all): TAGS arg must be a list from the beginning.
+;; *-remove-tags-from-all, *-rename-tag: Use bookmark-all-names - don't mapcar car over alist.
+;; *-all-tags-regexp-jump: Corrected to use same pred as *-all-tags-regexp-jump-other-window.
+;; *-(some|all)-tags-jump(-other-window): Use bookmarkp-has-tag-p - don't repeat the definition.
+;; *-read-tag(s)-completing: Removed unnecessary or.
+;; 2010/02/06 dadams
+;; *-write-file, *-empty-file: Corrected handling of ALT-MSG.
+;; 2010/02/05 dadams
+;; Added: bookmarkp-same-file-p, bookmarkp-empty-file.
+;; Bound bookmarkp-empty-file to C-x p 0, and added it to menus.
+;; *-bmenu-list, *-switch-bookmark-file: Use bookmarkp-same-file-p.
+;; bookmark-write-file: Added optional ALT-MSG arg.
+;; 2010/02/04 dadams
+;; Added: bookmarkp-bmenu-omit, bookmarkp-list-all-tags. Added to mouse-3 menu, Tags menus.
+;; 2010/02/01 dadams
+;; Added: bookmarkp-current-bookmark-file, bookmarkp-switch-bookmark-file,
+;; (redefinition of) bookmark-load, (redefinition of) bookmark-save,
+;; bookmarkp-toggle-saving-bookmark-file, bookmarkp-last-save-flag-value.
+;; *-bmenu-list: Restore bookmarkp-current-bookmark-file if appropriate.
+;; *-bmenu-mode-status-help: Show bookmarkp-current-bookmark-file.
+;; *-bmenu-define-full-snapshot-command, *-save-menu-list-state:
+;; Save bookmarkp-current-bookmark-file.
+;; Bound bookmarkp-switch-bookmark-file to L and C-x r L. Added both load commands to both menus.
+;; *-toggle-saving-menu-list-state: Changed binding to M-l. Error if init value is nil.
+;; Bound *-toggle-saving-bookmark-file to M-s and added to menu.
+;; Added bookmark-write to bookmarkp-bmenu-menubar-menu (Save As).
+;; bookmarkp-bmenu-menubar-menu: Added :help strings everywhere.
+;; bookmarkp-bmenu-mode-status-help: Added face legend.
+;; 2010/01/31 dadams
+;; Added: bookmarkp-tags-list, bookmarkp-read-tag-completing, bookmarkp-use-w32-browser-p,
+;; bookmarkp-bmenu-w32-open(-select|-with-mouse). Bind *-w32* to M-RET, V, M-mouse-2.
+;; *-default-handler: Call w32-browser if bookmarkp-use-w32-browser-p.
+;; *-bmenu-unomit-marked: Don't try to return to original position (duh).
+;; *-bmenu-goto-bookmark-named: Use eobp as loop condition. Call bookmark-bmenu-ensure-position.
+;; *-read-tags-completing:
+;; Added arg UPDATE-TAGS-LIST-P. Call bookmark-maybe-load-default-file.
+;; Use bookmarkp-tags-list if CANDIDATE-TAGS is nil. Update that var if UPDATE-TAGS-LIST-P.
+;; *-(add|remove)-tags: Added arg NO-CACHE-UPDATE-P. If nil, call bookmarkp-tags-list.
+;; *-remove-tags-from-all, *-rename-tag, *-bmenu-(add|remove)-tags-(to|from)-marked:
+;; Call bookmarkp-tags-list.
+;; *-remove-tags-from-all: Pass nil as tags arg to bookmarkp-read-tags-completing.
+;; *-rename-tag: Use bookmarkp-read-tag-completing, not read-string.
+;; 2010/01/29 dadams
+;; bookmarkp-describe-bookmark: Handle desktop bookmarks specifically.
+;; Added: bookmarkp-menu-popup-max-length.
+;; bookmark-completing-read: Use bookmarkp-menu-popup-max-length.
+;; bookmarkp-bmenu-state-file: Added missing default value for const.
+;; Don't add jump-other entry to menu-bar-bookmark-map (just use Jump To submenu).
+;; 2010/01/28 dadams
+;; bookmarkp-(all|some)-tags(-regexp)-jump(-other-window): Error if no bookmarks with the tags.
+;; bookmarkp-(all|some)-tags-jump(-other-window): Handle case where user enters no tags.
+;; Use :advertised-binding property for bookmark-jump(-other-window).
+;; Added: bookmarkp-bmenu-jump-menu.
+;; Added bookmarkp-bmenu-jump-menu to menu-bar-bookmark-map and bookmarkp-bmenu-menubar-menu.
+;; 2010/01/27 dadams
+;; Added: bookmarkp-every, bookmarkp-(all|some)-tags(-regexp)-jump(-other-window).
+;; 2010/01/26 dadams
+;; Added: bookmarkp-bmenu-dired-marked-local. Bound to M-d >.
+;; 2010/01/23 dadams
+;; Added: bookmarkp-handler-cp, bookmarkp-desktop-no-save-vars, bookmarkp-set-desktop-bookmark,
+;; bookmarkp-make-desktop-record, bookmarkp-jump-desktop, bookmarkp-desktop-read,
+;; bookmarkp-desktop-alist-only, bookmarkp-desktop-bookmark-p,
+;; bookmarkp-bmenu-mark-desktop-bookmarks, bookmarkp-bmenu-show-only-desktops,
+;; face bookmarkp-desktop.
+;; bookmarkp-bmenu-sort-by-bookmark-type: Add bookmarkp-handler-cp to the list (last).
+;; bookmarkp-bmenu-propertize-item: Add face bookmarkp-desktop for desktop bookmarks.
+;; Bound: bookmarkp-set-desktop-bookmark to C-x p K, C-x r K,
+;; bookmarkp-bmenu-mark-desktop-bookmarks to K M (and Mark menu),
+;; bookmarkp-bmenu-show-only-desktops to K S (and Show menu).
+;; bookmark-bmenu-mode doc string: Updated for new commands.
+;; Added autoload cookies for all defcustoms.
+;; 2010/01/20 dadams
+;; Added: bookmarkp-bmenu-mode-status-help. Bound to C-h m, ?.
+;; 2010/01/19 dadams
+;; bookmarkp-remote-file-bookmark-p: Include remote Dired bookmarks. Thx to Simon Harrison.
+;; Added: bookmarkp-describe-bookmark-internals, bookmarkp-bmenu-describe-this+move-(down|up),
+;; defalias for list-bookmarks.
+;; bookmarkp-describe-bookmark: Reformatted help output. Added more info about Dired bookmarks.
+;; bookmarkp-bmenu-describe-this-bookmark:
+;; C-u calls bookmarkp-describe-bookmark-internals. Bound also to C-h C-RET.
+;; 2010/01/18 dadams
+;; Added: bookmarkp-dired-subdirs.
+;; bookmarkp-make-dired-record, bookmarkp-jump-dired: Handle inserted and hidden dirs.
+;; bookmarkp-jump-dired: Use expand-file-name, not concat.
+;; 2010/01/17 dadams
+;; Added:
+;; bookmarkp-jump(-other-window)-map, bookmarkp-jump-1, bookmark-all-names (redefined),
+;; bookmarkp-read-bookmark-for-type, bookmarkp-dired-jump-current(-other-window),
+;; bookmarkp-(dired|(local-|remote-|non-)file|gnus|info|man|region|w3m)-jump(-other-window),
+;; bookmarkp-jump-to-type(-other-window).
+;; bookmark-jump(-other-window): Use bookmarkp-jump-1.
+;; bookmark-completing-read: Added optional args ALIST and PRED.
+;; bookmarkp-default-bookmark-name: Added optional arg ALIST.
+;; 2010/01/14 dadams
+;; bookmark-bmenu-surreptitiously-rebuild-list: Put back save-excursion & save-window-excursion.
+;; 2010/01/02 dadams
+;; Renamed *-bmenu-check-position to *-bmenu-ensure-position, per Emacs 23.2. Added defalias.
+;; 2010/01/01 dadams
+;; *-bmenu-(un)mark, *-bmenu-other-window, *-bmenu-rename: Call bookmark-bmenu-check-position.
+;; *-bmenu-delete: Don't call bookmark-bmenu-check-position again at end.
+;; *-bmenu-edit-bookmark: Call bookmark-bmenu-check-position at beginning, not end.
+;; 2009/12/30 dadams
+;; Added: bookmarkp-bmenu-header-lines, bookmarkp-bmenu-marks-width. Use everywhere.
+;; 2009/12/29 dadams
+;; Added: bookmarkp-make-bookmark-list-record, bookmarkp-jump-bookmark-list, face
+;; bookmarkp-bookmark-list.
+;; *-bmenu-propertize-item: Highlight bookmark-list bookmarks.
+;; *-bmenu-refresh-menu-list: Set bookmarkp-latest-bookmark-alist to refreshed list.
+;; Face *-local-directory: Made dark background version the inverse of light.
+;; *-bmenu-list-1: Use eq, not equal, test for bookmarkp-omitted-alist-only as filter fn.
+;; *-bmenu-define(-full-snapshot)-command: Include bookmarkp-bmenu-omitted-list in saved state.
+;; 2009/12/26 dadams
+;; Added: bookmarkp-bmenu-omitted-list, bookmarkp-bmenu-show-only-omitted, bookmarkp-unomit-all,
+;; bookmarkp-bmenu-omit/unomit-marked, bookmarkp-bmenu-(un-)omit-marked,
+;; bookmarkp-omitted-alist-only.
+;; Bind *-bmenu-omit/unomit-marked, *-bmenu-show-only-omitted, *-unomit-all to O>,OS,OU.
+;; Added omit/un-omit stuff to Bookmark+ menu.
+;; bookmarkp-remove-assoc-dups, bookmarkp-sort-and-remove-dups: Added optional arg OMIT.
+;; bookmark-delete: Update bookmarkp-bmenu-omitted-list.
+;; bookmarkp-save-menu-list-state, bookmark-bmenu-list:
+;; Save/restore bookmarkp-bmenu-omitted-list as part of state.
+;; bookmark-bmenu-list-1: Treat omitted list when bookmarkp-omitted-alist-only.
+;; bookmarkp-marked-bookmark-p: Arg can now be a bookmark (or a bookmark name).
+;; bookmarkp-bmenu-unmark-all: Start by going forward 2 lines, not 1, if user hit RET.
+;; bookmarkp-bmenu-make-sequence-from-marked:
+;; Added optional arg DONT-OMIT-P. If nil, omit marked bookmarks.
+;; If the seq bookmark already exists, prompt to add to it or replace it.
+;; Go to the new bookmark in the menu list.
+;; 2009/12/15 dadams
+;; Added: bookmarkp-sequence-jump-display-function, bookmarkp-sequence, bookmarkp-function,
+;; bookmarkp-bmenu-make-sequence-from-marked, bookmarkp-jump-sequence,
+;; bookmarkp-sequence-bookmark-p, bookmarkp-make-function-bookmark,
+;; bookmarkp-jump-function, bookmarkp-function-bookmark-p.
+;; bookmarkp-describe-bookmark: Update for sequence and function bookmarks.
+;; bookmark-bmenu-list: Use condition-case when read from bookmarkp-bmenu-state-file.
+;; Bind emacs-lisp-mode-hook to nil.
+;; bookmark-bmenu-surreptitiously-rebuild-list: Use save-current-buffer.
+;; bookmarkp-bmenu-propertize-item: Add faces to function and sequence bookmarks.
+;; bookmarkp-bmenu-menubar-menu: Add *-make-sequence-*-from-marked, *-make-function-bookmark.
+;; bookmark--jump-via: Call *-record-visit with BATCH arg, to preserver point in menu list.
+;; bookmark-bmenu-list-1: fit-frame only if buffer is *Bookmark List*.
+;; 2009/12/13 dadams
+;; *-alist-only: Call bookmark-maybe-load-default-file.
+;; 2009/12/11 dadams
+;; Added: bookmarkp-list-defuns-in-commands-file, bookmarkp-remove-dups.
+;; 2009/12/06 dadams
+;; Added: bookmarkp-bmenu-mouse-3-menu (bound to mouse-3),
+;; bookmarkp-bmenu-(menubar|define-command|sort|show|tags|mark)-menu.
+;; bookmark-bmenu-delete: Remove newly flagged bookmark from bookmarkp-bookmark-marked-list.
+;; bookmarkp-define-tags-sort-command: Save macroexpanded definition in
+;; bookmarkp-bmenu-commands-file.
+;; 2009/12/04 dadams
+;; Added: bookmarkp-bmenu-define-full-snapshot-command (bound to C),
+;; bookmarkp-define-tags-sort-command.
+;; bookmarkp-bmenu-mark-bookmarks-tagged-regexp: Removed extra forward-line if we mark line.
+;; 2009/12/03 dadams
+;; Added: bookmarkp-bmenu-define-command (bound to c), bookmarkp-bmenu-commands-file.
+;; bookmark-bmenu-list: Read bookmarkp-bmenu-commands-file.
+;; bookmarkp-sort-and-remove-dups: Bug fix - return the list even when null sort function.
+;; 2009/11/01 dadams
+;; Added: *-bmenu-check-position (redefinition), bmkext-jump-* defaliases.
+;; *-(w3m|man|gnus)-bookmark-p: Recognize the aliases.
+;; *-jump-man: Bind Man-notify-method.
+;; *-bmenu-goto-bookmark-named: Check the text property, instead of searching.
+;; *-bmenu-bookmark: Wrap in condition-case.
+;; 2009/10/31 dadams
+;; Added: bookmark-bmenu-list-1. bookmarkp-toggle-saving-menu-list-state (C-t),
+;; bookmarkp-bmenu-state-file, bookmarkp-bmenu-first-time-p,
+;; bookmarkp-last-bmenu-(bookmark|state-file), bookmark-exit-hook-internal
+;; (redefinition), bookmarkp-save-menu-list-state.
+;; bookmark-bmenu-list: Restore menu-list state if appropriate. Call bookmark-bmenu-list-1.
+;; bookmarkp-bmenu-quit: If *-bmenu-state-file is non-nil, save the state.
+;; bookmark-write-file: Use case, not cond.
+;; bookmark-set: Use command name as default for man-page bookmark name.
+;; bookmark-delete: Update bookmarkp-latest-bookmark-alist.
+;; 2009/10/28 dadams
+;; Renamed: bookmarkp-bookmark-marked-p to bookmarkp-marked-bookmark-p
+;; bookmarkp-bmenu-sort-by-gnus-thread to bookmarkp-bmenu-sort-by-Gnus-thread.
+;; Added: bookmarkp-man, bookmarkp-make-(wo)man-record, bookmarkp-jump-(wo)man,
+;; bookmarkp-man-bookmark-p, bookmarkp-bmenu-mark-man-bookmarks,
+;; bookmarkp-bmenu-show-only-man-pages, bookmarkp-man-alist-only.
+;; *-bmenu-propertize-item: Handle (wo)man bookmarks. Use bookmarkp-info-bookmark-p.
+;; *-regexp-filtered-*: Use bookmarkp-remove-if-not.
+;; *-write-file: Remove text properties from file name also.
+;; *-regexp-filtered-(tags|(bookmark|file)-name)-alist-only: Use *-remove-if-not.
+;; 2009/10/26 dadams
+;; Added: bookmarkp-bmenu-mark-*-bookmarks, bmenu-mark-bookmarks-satisfying.
+;; Bound those and *-show-only-* accordingly.
+;; bookmarkp-file-alist-only: Redefined to just use *-file-bookmark-p.
+;; 2009/10/25 dadams
+;; bookmarkp-bmenu-propertize-item: Put bookmark name on line as text property.
+;; bookmark-bmenu-bookmark: Get bookmark name from text property bookmarkp-bookmark-name.
+;; Removed: bookmarkp-latest-sorted-alist.
+;; bookmark-bmenu-list: Use bookmarkp-bmenu-title only if defined.
+;; 2009/10/21 dadams
+;; Added: bookmarkp-barf-if-not-in-menu-list. Use in place of its body.
+;; Added: bookmarkp-bmenu-mark-bookmarks-tagged-regexp. Bound to T m %.
+;; Added: bookmarkp-record-visit. Use in *--jump-via. Replaces next two removals.
+;; Removed: bookmarkp-add-or-update-time, bookmarkp-increment-visits.
+;; Renamed: *-record-(end|front|rear)-context(-region)-string'.
+;; New names: bookmarkp-(end-)position-(pre|post)-context(-region).
+;; *-bmenu-describe-this-bookmark: Added *-barf-if-not-in-menu-list.
+;; *-bmenu-(un)mark-all, *-bmenu-regexp-mark, *-bmenu-toggle-marks:
+;; Removed with-current-buffer.
+;; 2009/10/20 dadams
+;; Added: bookmarkp-bmenu-filter-function, bookmarkp-bmenu-title.
+;; Removed: bookmarkp-bmenu-called-from-inside-p.
+;; *-bmenu-list:
+;; Removed TITLE arg. Get title from bookmarkp-bmenu-title or default.
+;; Use interactive-p and absence of menu list, not *-bmenu-called-from-inside-p, as the
+;; criterion for removing marks. Fixes bugs such as bookmark creation removing marks.
+;; *-define-sort-command, *-bmenu-execute-deletions, *-increment-visits,
+;; *-add-or-update-time, *-bmenu-show-only-*, *-bmenu-show-all,
+;; *-bmenu-refresh-menu-list, *-bmenu-toggle-show-only-(un)marked,
+;; *-bmenu-filter-alist-by-regexp, *-bmenu-reverse(-multi-sort)-order,
+;; *-bmenu-change-sort-order:
+;; Do not bind or set *-called-from-inside-p.
+;; *-bmenu-show-only-*, *-bmenu-show-all, *-bmenu-filter-alist-by-regexp:
+;; Set *-bmenu-filter-function, *-bmenu-title.
+;; *-bmenu-show-all:
+;; Set *-latest-bookmark-alist to bookmark-alist.
+;; *-bmenu-refresh-menu-list: Fix so that it in fact refreshes.
+;; Do not use *-bmenu-surreptitiously-rebuild-list and *-bmenu-check-position.
+;; Bind bookmark-alist to last alist (filtered or not), and call *-bmenu-list.
+;; *-bmenu-surreptitiously-rebuild-list:
+;; Do not use save*-excursion. Do not get current title and pass it to *-bmenu-list.
+;; *-file-alist-only:
+;; Removed optional arg. We have *-local-file-alist-only for that.
+;; *-regexp-filtered-alist-only, *-bmenu-filter-alist-by-regexp:
+;; Remove REGEXP arg - use bookmarkp-bmenu-filter-pattern.
+;; *-bmenu-filter-incrementally:
+;; Raise error if not in *Bookmark List*.
+;; Use just bookmarkp-bmenu-filter-alist-by-regexp in timer - pass no regexp arg.
+;; Added: bookmarkp-some, *-bmenu-filter-(file-name|tags)-incrementally,
+;; *-bmenu-filter-alist-by-(file-name|tags)-regexp,
+;; *-regexp-filtered-(file-name|tags)-alist-only.
+;; Renamed: *-bmenu-filter-incrementally to *-bmenu-filter-bookmark-name-incrementally,
+;; *-bmenu-filter-alist-by-regexp to *-bmenu-filter-alist-by-bookmark-name-regexp,
+;; *-regexp-filtered-alist-only to *-regexp-filtered-bookmark-name-alist-only.
+;; Bound these commands to P B, P F, and P T. Updated bookmark-bmenu-mode doc string.
+;; 2009/10/18 dadams
+;; Added: *-bmenu-filter-(incrementally|delay|prompt|pattern|timer|alist-by-regexp),
+;; *-bmenu-read-filter-input, *-regexp-filtered-alist-only,
+;; *-bmenu-cancel-incremental-filtering.
+;; *-bmenu-execute-deletions: Don't update menu list if this is a no-op.
+;; Updated Commentary.
+;; Thx to Thierry Volpiatto.
+;; Added: *-marked-cp, *-bmenu-sort-marked-before-unmarked. Bound to s >.
+;; *-define-sort-command: Use copy-sequence for default value.
+;; 2009/10/17 dadams
+;; Added: *-read-tags-completing, *-set-union, *-tag-history, *-describe-bookmark,
+;; *-bmenu-describe-this-bookmark. Bound *-bmenu-describe-this-bookmark to C-h RET.
+;; Use *-read-tags-completing instead of *-read-tags.
+;; *-sort-orders-for-cycling-alist: Use copy-sequence.
+;; *-bmenu-change-sort-order: Use member, not memq.
+;; *-get-bookmark: Handle case of non-string, non-cons. Document NOERROR in doc string.
+;; *-bmenu-execute-deletions: Fix so marks aren't removed if when delete. Thx to Thierry.
+;; Convert recorded time to an Emacs time spec:
+;; *-make-record-default, -add-or-update-time: Use current-time, not bookmark-float-time.
+;; *-get-visit-time: Convert a deprecated time entry to an Emacs time spec.
+;; *-bookmark-last-access-cp: Convert recorded time to a number for comparison.
+;; Added: *-bmenu-show-filenames (redef of vanilla: put props on whole line, fit frame).
+;; Removed: old-bookmark-insert-location.
+;; *-insert-location: Do not call original. Redefined: do not add text properties.
+;; *-bmenu-list, *-bmenu-hide-filenames: Put properties on line up to max width.
+;; *-bmenu-goto-bookmark-named: Allow trailing whitespace, since we use the whole line now.
+;; *-bmenu-list: Use pop-to-buffer, not switch-to-buffer. Use do-list, not mapcar.
+;; *-bmenu-hide-filenames: fit-frame-if-one-window.
+;; *-bmenu-propertize-item: Better help-echo text.
+;; Updated bookmark-alist doc string to mention visits, time, and tags entries.
+;; 2009/10/16 dadams
+;; Added tags feature.
+;; Added: *-(get|read)-tags, *-has-tag-p, *-remove(-all)-tags(-from-all),
+;; *-bmenu-remove-tags-from-marked, *-add-tags(-to-marked), *-rename-tag,
+;; *-bmenu-(un)mark-bookmarks-tagged-(all|none|some|not-all),
+;; *-bmenu-mark/unmark-bookmarks-tagged-(all/none|some/not-all).
+;; Bound to prefix key T.
+;; *-bmenu-mode: Updated doc string.
+;; Added: bookmarkp-default-bookmark-name. Use as default instead of *-current-bookmark.
+;; Renamed: *-maybe-save-bookmark to *-maybe-save-bookmarks.
+;; Menu-list commands: Raise an error if command is used outside the menu list.
+;; 2009/10/15 dadams
+;; Added: *-bmenu-(search|query-replace)-marked-bookmarks-regexp. Bound to M-a, M-q.
+;; Renamed: *-non-marked-bookmarks-only to *-unmarked-bookmarks-only,
+;; *-bookmark-marked-alist to *-bmenu-marked-bookmarks.
+;; *-increment-visits, *-add-or-update-time:
+;; Set *-bmenu-called-from-inside-p to t, so we don't remove marks.
+;; Redefined *-bmenu-bookmark to get name from *-latest-sorted-alist. Thx to Thierry V.
+;; *-bmenu-surreptitiously-rebuild-list, *-bmenu-list:
+;; Removed optional arg DONT-TOGGLE-FILENAMES-P.
+;; *-bmenu-execute-deletions, *-bmenu-toggle-show-only-(un)marked, *-bmenu-(un)mark-all,
+;; *-bmenu-regexp-mark, *-bmenu-toggle-marks:
+;; Do not bother with *-bmenu-toggle-filenames and rebuilding the menu list.
+;; 2009/10/14 dadams
+;; Added: *-bmenu-delete (redefinition), *-isearch-bookmarks,
+;; *-bmenu-isearch(-marked)-bookmarks(-regexp), *-isearch-next-bookmark-buffer.
+;; Bound multi-isearch commands to M-s a C(-M)-s.
+;; 2009/10/13 dadams
+;; Added: *-make-dired-record, *-jump-dired, *-dired-bookmark-p, *-dired-alist-only,
+;; *-bmenu-show-only-dired. Bound *-bmenu-show-only-dired to M-d.
+;; bookmarkp-file-bookmark-p: Include bookmarks that have the Dired handler.
+;; Moved *-sort-orders-for-cycling-alist defcustoms after *-define-sort-command calls.
+;; Call bookmarkp-msg-about-sort-order only when interactive.
+;; *-add-or-update-time, *-increment-visits: Do not save each time we access a bookmark.
+;; Updated doc string of bookmark-alist and Commentary.
+;; 2009/10/09 dadams
+;; Added: bookmarkp-bmenu-delete-marked. Bound it to D.
+;; bookmarkp-sort-orders-for-cycling-alist.
+;; Renamed: bookmarkp-sort-functions-alist to bookmarkp-sort-orders-alist,
+;; bookmarkp-sort-function to bookmarkp-sort-comparer.
+;; bookmark-bmenu-execute-deletions: Added optional arg, for *-bmenu-delete-marked.
+;; *-sort-function: Changed default value to sorting by bookmark type (`s k').
+;; *-bmenu-change-sort-order: Use *-sort-orders-for-cycling-alist, not all sort orders.
+;; Updated Commentary and doc string (bookmark-bmenu-mode).
+;; 2009/10/08 dadams
+;; Added: *-bmenu-sort-by-(w3m-url|gnus-thread), *-(gnus|w3m)-cp, *-cp-not,
+;; *-local-file-(accessed|updated)-more-recently-cp, *-bmenu-sort-by-bookmark-type.
+;; Renamed: *-bmenu-sort-by(-last)-file-(size|type|access|update) to
+;; *-bmenu-sort-by(-last)-local-file-(size|typeaccess|update),
+;; *-file-visited-more-recently-cp to *-local-file-accessed-more-recently-cp,
+;; *-file-(size|type)-cp to *-local-file-(size|type)-cp.
+;; Removed: *-file-(device|gid(-chg)|inode|last-(access|update|status-change)|links|modes
+;; |uid)-cp.
+;; Bound *-bmenu-sort-by-bookmark-type to `s k'.
+;; *-define-file-sort-predicate: Use *-file-bookmark-p, not *-local-file-bookmark-p.
+;; *-msg-about-sort-order: Added optional arg PREFIX-ARG. Use in: *-show-(all|only-*).
+;; 2009/10/07 dadams
+;; Renamed: *-bmenu-sort-by-last-visit-time to *-bmenu-sort-by-last-bookmark-access,
+;; *-bmenu-sort-by-visit-frequency to *-bmenu-sort-by-bookmark-visit-frequency,
+;; *-visited-more-recently-cp to *-bookmark-last-access-cp.
+;; 2009/10/06 dadams
+;; Added: bookmarkp-msg-about-sort-order.
+;; bookmark-completing-read: Simple sort when use menu-bar menu.
+;; 2009/10/05 dadams
+;; Added: *-make-plain-predicate, *-reverse-multi-sort-order, *-multi-sort,
+;; *-define-file-sort-predicate, *-bmenu-sort-by-file-*, *-file-attribute-*-cp,
+;; and aliases *-file-*-cp, *-current-sort-order.
+;; Redefined sorting to allow multi-predicates:
+;; Redefined: *-sort-function, *-sort-and-remove-dups, *-define-sort-command,
+;; *-sort-functions-alist.
+;; Bound keys with `s f' prefix to file-sorting commands
+;; *-current-sort-order: Use rassoc instead of rassq now.
+;; Swap keys s and S. S is now bookmark-bmenu-save. s is not the sorting prefix key.
+;; bookmark-bmenu-mode: Mention S key explicitly here (even though it is also
+;; mentioned in the vanilla part of the doc string).
+;; 2009/10/04 dadams
+;; *-bmenu-change-sort-order-repeat: Require repeat.el.
+;; Renamed: bookmarkp-current-sec-time to bookmarkp-float-time.
+;; *-float-time: Added arg, so it's the same as float-time (for Emacs 20).
+;; Bind *-reverse-sort-order to `S R'.
+;; *-remote-file-bookmark-p: Removed extra rem-file in last and.
+;; *-non-file-bookmark-p: Ensure it's not a remote file, before calling file-exists-p.
+;; 2009/10/03 dadams
+;; Added: bookmarkp-file-remote-p, bookmarkp-buffer (face).
+;; bookmarkp-non-file (face): Changed to gray.
+;; *-default-handler, *-bmenu-propertize-item, *-(info|file)-bookmark-p:
+;; Support Emacs 20-21 Info-node bookmarks.
+;; bookmarkp-bmenu-propertize-item: Use different face for existing buffers.
+;; Use bookmarkp-non-file-filename.
+;; bookmarkp-non-file-bookmark-p: Include buffer bookmarks for nonexistent buffers.
+;; bookmarkp-remote-file-bookmark-p: Use bookmarkp-file-remote-p.
+;; bookmark-handle-bookmark:
+;; Redefine for all Emacs versions. Handle buffer (non-file) bookmarks.
+;; Reordered some function definitions.
+;; 2009/10/02 dadams
+;; Added: bookmarkp-bmenu-goto-bookmark-named, bookmarkp-latest-sorted-alist.
+;; *-sort-and-remove-dups: Set *-latest-sorted-alist (not used yet).
+;; *-define-sort-command, *-bmenu-change-sort-order, *-reverse-sort-order:
+;; Bind *-bmenu-called-from-inside-p to t, to prevent losing marks.
+;; Restore cursor position to same bookmark after sorting - use *-goto-bookmark-named.
+;; *-bmenu-surreptitiously-rebuild-list, *-bmenu-list: Added arg DONT-TOGGLE-FILENAMES-P.
+;; *-bmenu-execute-deletions, *-bmenu-toggle-show-only-(un)marked:
+;; Call *-surreptitiously-* with arg DONT-TOGGLE-FILENAMES-P.
+;; *-bmenu-hide-filenames: Simplify - don't get to position by searching backward.
+;; *-handle-region-default: Use forward-line, not goto-line.
+;; Thx to Thierry V.
+;; 2009/10/01 dadams
+;; Added: bookmarkp-some-unmarked-p.
+;; Renamed: *-bmenu-toggle-show-only-<TYPE> to *-bmenu-show-only-<TYPE>,
+;; *-bmenu-called-from-inside-flag to *-bmenu-called-from-inside-p.
+;; bookmarkp-some-marked-p: Do not test bookmarkp-bookmark-marked-alist.
+;; Arg must be required (explicit). Changed calls accordingly.
+;; bookmark-bmenu-mode: Cleaned up doc string.
+;; bookmark-bmenu-((un)mark|rename|edit-*|toggle-marks|surreptitiously-rebuild-list),
+;; bookmarkp-root-or-sudo-logged-p, bookmarkp-jump-w3m-(new-session|only-one-tab),
+;; bookmarkp-some-marked-p:
+;; Inline let vars used only once.
+;; bookmarkp-bmenu-toggle-show-only-marked:
+;; Test bookmarkp-some-unmarked-p, not bookmarkp-some-marked-p,
+;; and include *-before-hide-unmarked in the test.
+;; bookmarkp-bmenu(-toggle)-show-only-*: Display status message.
+;; bookmarkp-bmenu-toggle-show-only-(un)marked: Fit frame.
+;; bookmark-prop-set: Fixed, so it handles old bookmark format also.
+;; 2009/10/01 Thierry Volpiatto
+;; Removed: bookmarkp-bmenu-restore-marks.
+;; bookmark-bmenu-list:
+;; Do the mark restoration in line, at the same time as the annotation * restoration.
+;; Simplify use of START and END.
+;; 2009/09/30 dadams
+;; bookmarkp-bmenu-regexp-mark: Remove binding of bookmark-alist.
+;; bookmark-bmenu-(un)mark, bookmarkp-bmenu-edit-bookmark (remove first call only),
+;; bookmark-bmenu-other-window, bookmark-bmenu-rename, bookmarkp-bmenu-restore-marks:
+;; Remove bookmark-bmenu-check-position (done by bookmark-bmenu-bookmark anyway).
+;; bookmark-insert-location: Fix interactive spec for Emacs < 22.
+;; bookmark-location: Return "" instead of raising error, if no location found.
+;; bookmarkp-current-sec-time: Move the let: do not call current-time unless we need to.
+;; bookmarkp-bmenu-unmark-all: forward-line only 1, not 2. Thx to Thierry.
+;; bookmark-bmenu-mode: Updated doc string - bindings and mention options.
+;; bookmarkp-bmenu-propertize-item: For buffer, check also against " - no file -".
+;; 2009/09/29 dadams
+;; bookmark-bmenu-unmark: Use delete, not remove.
+;; Removed: bookmark-bmenu-check-position, bookmarkp-maybe-sort.
+;; Added: bookmarkp-sort-and-remove-dups, bookmarkp-remove-assoc-dups,
+;; bookmarkp-face-prop, bookmarkp-bad-bookmark, bookmark-menu-heading (Emacs 20,21),
+;; bookmark-bmenu-bookmark (redefinition).
+;; *-bmenu-toggle-show-only-*: Do not call-interactively.
+;; bookmarkp-bmenu-(un)mark-all:
+;; Handle bookmark-bmenu-toggle-filenames (wrapper).
+;; Remove bookmark-bmenu-check-position - just ensure within menu list.
+;; bookmarkp-bmenu-mark-all: Move save-excursion so it applies to all movements.
+;; Message stating number marked.
+;; bookmarkp-bmenu-unmark-all: Use with-current-buffer ensure in menu list.
+;; Use bookmark-bmenu-unmark.
+;; Fixed U bindings for bookmarkp-bmenu-unmark-all.
+;; bookmarkp-bmenu-regexp-mark:
+;; Remove bookmark-bmenu-check-position - just ensure in menu list.
+;; bookmarkp-bmenu-toggle-marks: Use forward-line 2, to ensure in menu list.
+;; Message stating number marked.
+;; bookmark-bmenu-list, bookmarkp-bmenu-propertize-item: Use bookmarkp-face-prop.
+;; bookmark-bmenu-list: Don't start applying the faces until column 2.
+;; Removed key bindings in bookmark-map for *-toggle-show-only-*.
+;; Redefined faces, esp. for a light background.
+;; Use font-lock-face or face property, depending on Emacs version.
+;;
+;; 2009-06-09 to 2009-09-27 Thierry Volpiatto and dadams
+;; New features, as follows.
+;; See also the change log at
+;; http://mercurial.intuxication.org/hg/bookmark-icicle-region/.
+;; 2090-09-27 Rewrote sorting and unmarking code. (+ Updates to doc, names.)
+;; Unmarking is now like Dired & query-replace.
+;; Sorting is via one sort function; sort predicates do all the sorting.
+;; Can now cycle sort orders with S S S...
+;; Sort cmds now cycle among normal, reverse, off.
+;; Add: *-define-sort-command (macro), *-assoc-delete-all, *-upcase,
+;; *-get-visits-count, *-get-visit-time, *-sort-functions-alist.
+;; Remove docstring from defalias (for Emacs 20).
+;; 2009-09-26 Fix *-bmenu-mode doc (defadvice).
+;; 2009-09-25 *-bmenu-edit, *-bmenu-sort-1: Fix bmk retrieval code.
+;; Redefine *-bmenu-unmark. Add: *-bmenu-toggle-marks.
+;; Bind *-bmenu-unmark-all-bookmarks to M-DEL. Reorder code.
+;; Rename: *-bmenu-unmark-all-(bookmarks|(delete|mark)-flag)',
+;; *-bmenu-unmark-all-bookmarks-1.
+;; Change sort predicates in defalias. Rename bmk entry visit to visits.
+;; Remove: *-bmenu-show-number-of-visit.
+;; 2009-09-22 Rewrote sorting code. Renamed unmarking fns.
+;; 2009-09-21 Rename mark/unmark cmds to have -bmenu.
+;; Add: *-bmenu-called-from-inside-flag - set it in (un)hide marks fns.
+;; 2009-09-20 *-write-file: Remove text properties before saving.
+;; Remove all marks only in current display.
+;; 2009-09-19 *-current-sec-time: Protect with fboundp for Emacs 20.
+;; *-bmenu-sort-1: Add msg showing sort method.
+;; Change key S-A to S-S (A is annotations).
+;; 2009-09-18 Improve sorting by visit frequency. Always increment when jump.
+;; Fix increment visit fn. Allow sorting by last visited.
+;; When visit values are equal, sort with string-lessp.
+;; Add TIME bookmark-alist entry. *-make-record-default: Add time entry.
+;; Fix: bad parens, errors in sorting predicate. Rename fns.
+;; Use single fn to sort using diff methods.
+;; Add: *-bmenu-refresh-alist (bind to g).
+;; 2009-09-16 Add: *-toggle-sorting-by-most-visited, *-reset-visit-flag,
+;; *-bmenu-show-number-of-visit.
+;; Redefine *-prop-set. Improve *-toggle-sorting-by-most-visited.
+;; Add auto-doc to header. *-bmenu-mode: Add missing key.
+;; Update menu-list after jumping.
+;; Increment save counter when jump with visit flag.
+;; 2009-09-15 Record number of visits. Added sorting by most visits.
+;; 2009-09-14 Add doc string. Update defadvice doc string wrt keys.
+;; 2009-09-12 Add: fns to mark all, unmark D or > or all, *-bmenu-reset-alist.
+;; Fix keymap (Emacs 20). *-unmark-all-bookmarks1: Move the save-excursion.
+;; 2009-09-11 Add: *-bmenu-check-position (redef to improve performance),
+;; *-unmark-all-bookmarks, *-current-list-have-marked-p,
+;; *-bookmark-marked-p, *-(non-)marked-bookmarks-only.
+;; *-bmenu-hide-unmarked: Add toggling. Restore lost fn.
+;; Reorder code. Bind cmds in *-bmenu-mode-map.
+;; *-bmenu-hide-marked: Do not hide if no marked in current filter.
+;; Improve: *-bmenu-hide(-not)-marked-bookmark, (un)hide marked fns.
+;; 2009-09-10 Fix *--restore-all-mark, *-bmenu-regexp-mark.
+;; *-bmenu-list: Add *-restore-all-mark.
+;; *-bmenu-mark: Push marked bmk to marked list.
+;; Add: bookmarkp-bookmark-marked-list, *-bmenu-quit.
+;; 2009-09-09 *-maybe-sort-alist: Use copy-sequence.
+;; So remove fixes for *-rename, *-edit-bookmark.
+;; *-yank, *-rename', *-set: Fix yanking.
+;; Remove non-file bmks from file-only list.
+;; Add: *-bmenu-list-only-non-file-bookmarks, *-maybe-message (Emacs 20),
+;; *-bmenu-mark-bookmark-matching-regexp, *-bmenu-hide-marked-bookmark,
+;; *-bmenu-hide-not-marked-bookmark, *-bmenu-mark (redefinition).
+;; *-write-file: Improve performance.
+;; *-non-file-alist-only: Remove unused def.
+;; Fix: hide marked/unmarked with toggle-filenames, keymap for Emacs 20.
+;; Improve comments, doc strings.
+;; *-bmenu-mark-bookmark-matching-regexp: Fix while loop.
+;; 2009-09-08 bookmark-store: Remove duplicate setq of *-current-bookmark.
+;; 2009-09-07 Reorganize (reorder), add comments, improve doc strings.
+;; Change binding of *-bmenu-relocate from R to M-r.
+;; 2009-09-06 bookmark-rename: Redefine with new arg BATCH.
+;; *-bmenu-rename: Go to new pos, not old.
+;; *-edit-bookmark, bookmark-rename: Fix display update for Emacs 20.
+;; 2009-09-05 Add: *-edit-bookmark, *-bmenu-edit-bookmark, *-maybe-save-bookmark.
+;; 2009-09-04 Require cl. Allow RET in Emacs 20. Add doc string.
+;; *-fix-bookmark-alist-and-save:
+;; 2009-09-03 Fix *-fix-bookmark-alist-and-save:
+;; Use error, not message. Change value for setcdr.
+;; Do not use push with non-var (cl).
+;; bookmark-delete:
+;; Redefine, to fix vanilla bug: increment count even when BATCHP is non-nil.
+;; *-non-file-name: Change to - no file -. *-bmenu-list: Add arg FILTER-ON.
+;; *-bmenu-execute-deletions: Use delete, not remove.
+;; Add: *-replace-regexp-in-string.
+;; bookmark-set: Fix *-yank-point for region case. Fix bad parens.
+;; 2009-09-02 Add: *-non-file-filename. *-fix-bookmark-alist-and-save: Fix msg.
+;; Require cl (gensym). *-at-bol/eol' -> line-*-position (for Emacs 20).
+;; Redefine *-bmenu-execute-deletions,
+;; *-bmenu-surreptitiously-rebuild-list.
+;; Update current filtered display - do not reload & display all bmks.
+;; Add redefinitions of *-bmenu-rename', *-yank-word to fix vanilla bugs:
+;; *-bmenu-rename: Do not call *-bmenu-list twice.
+;; *-yank-word: Do not insert whitespace.
+;; Rename *-last-bookmark-alist-in-use to *-latest-bookmark-alist.
+;; 2009-09-01 Fix: Loading of new doc for bookmark-alist (add vacuous defvar).
+;; *-bmenu-(list|hide-filenames): start -> end, end -> start.
+;; Removed extraneous quote mark that caused problems.
+;; Save only if condition-case exits OK.
+;; 2009-08-31 Fixes: Test for non-file bmk. Filename for Gnus bmks.
+;; Compatibility of bookmark-alist with vanilla Emacs.
+;; Require info.el and ffap.el when needed.
+;; Add: *-line-number-at-pos (for Emacs 20),
+;; *-bmenu-other-window (redefinition).
+;; Rename *-propertize-bookmark-list to *-propertize-bmenu-item.
+;; 2009-08-30 Fix: Increment *-alist-modification-count when relocate region,
+;; and maybe save.
+;; Move code adding properties to bookmarks out of *-bmenu-list.
+;; mapc -> mapcar. *-bmenu-hide-filenames: Redefine.
+;; 2009-08-29 Remove refresh code.
+;; 2009-08-27 Added: *-local-directory-bookmark-p, *-local-file-alist-only,
+;; *-non-file-alist-only.
+;; *-file-bookmark-p: Redefined to exclude bmks with handlers.
+;; Renamed fns and faces.
+;; 2009-08-25 Fit frame after display menu list.
+;; Refresh list when toggle filename visibility.
+;; 2009-08-24 Fix: *-bmenu-list for remote files, bookmark-set, *-remote-file-bookmark-p.
+;; Ensure arg to file-remote-p is not nil.
+;; Recenter region only if it is visible.
+;; 2009-08-23 Remove old *-location. *-bmenu-list: Add isw3m.
+;; bookmark-set:
+;; Redefine for older Emacs. Use a default prompt for gnus, w3m.
+;; Use *-name-length-max for title when region is active.
+;; Ensure bookmark is on one line.
+;; 2009-08-22 Try to handle tramp ftp files.
+;; Do not fail if bookmark has empty filename entry.
+;; Show region end pos using exchange-point-and-mark.
+;; 2009-08-21 Remove all cl stuff (list*, loop, etc.). Add *-remove-if(-not).
+;; Remove compile-time require of cl.
+;; Add predicates *-(region|gnus|w3m|info|(remote-|local-)file)-bookmark-p.
+;; Redefine alist-only functions to optimize and use new preds.
+;; 2009-08-20 *--jump-via: Fix to show relocated region before ask whether to save.
+;; *-relocate-region: Fix ar-str. Rename a var. Add: *-region-activated-p.
+;; Revert chgs.
+;; 2009-08-19 Update/fix commentary: bookmark-alist, linkd.
+;; *-default-handler, *-handle-region-default:
+;; Get bmk record from name only once.
+;; *-save-new-region-location: Move t inside progn.
+;; 2009-08-16 Use prefix bookmarkp where appropriate.
+;; 2009-08-15 Improve comments, doc strings. Rename fns, vars.
+;; Add :group with prefix bookmarkp.
+;; 2009-08-09 Fix doc strings.
+;; 2009-08-08 bookmark-set: Update doc string. Show keys in C-h m.
+;; 2009-08-07 *-jump: Fix to jump in same window (thx to Henry Atting).
+;; *-at-bol/eol' -> line-*-position.
+;; 2009-08-01 bookmark-store: Fix for Emacs 20.
+;; 2009-07-27 Ensure we start on an empty w3m buffer. Add: *-w3m-allow-multi-tabs.
+;; 2009-07-24 *-bmenu-mode-map: Define some new keys.
+;; 2009-07-23 *-bmenu-list: Add path to file in help-echo.
+;; 2009-07-19 Fix title underline. Highlight bookmark if root logged with tramp.
+;; Add face for sudo.
+;; 2009-07-18 Add: filter functions, option for bookmark-bmenu-list.
+;; Remove toggle region.
+;; *-bmenu-list-only-files-entries: Add prefix arg to show remote.
+;; 2009-07-14 Add a forgotten test.
+;; 2009-07-13 Fix errors. Give pos in msg even if no search.
+;; *-from-bob/eob: Fixed like old strict.
+;; Remove *-relocate-region-(method|from-limits).
+;; Remove unused code in record fns. Add: *-relocate-region-function.
+;; 2009-07-12 Do not pass args to relocation routines. Remove use of flet.
+;; Use skip-chars-*ward. Use forward-line, not beginning-of-line.
+;; Remove save-excursion around message. Correct typo f(ree var BMK).
+;; 2009-07-11 Fix *-relocate-region-strict. Rename fns, adjust defcustom.
+;; Save relocated region after pushing mark. Add comments.
+;; 2009-07-10 New retrieve fn. Add looking-* fns.
+;; 2009-07-08 Simplify record fns. Add doc strings. Add: *-save-relocated-position.
+;; Fix: updating when relocate (wrt new record fns), string closing,
+;; free vars, parens, names.
+;; 2009-07-06 Fix: *-bmenu-list wrt windows, Info colors.
+;; 2009-07-04 Rename fns to record, vars, args of retrieve fns. Big changes, fixes.
+;; 2009-07-01 Fix comments. *-retrieve-region-strict: improve when out of context.
+;; 2009-06-30 Fix: free vars, *-retrieve-region, provide (name).
+;; 2009-06-29 Fix: w3m handler, file name for non-file, *-simple-retrieve-position.
+;; Add: *-retrieve-region-strict.
+;; 2009-06-28 Add: *-retrieve-region-method-is, *-retrieve-region-lax,
+;; fns to retrieve regions.
+;; Use buffer again, not buffer-name.
+;; 2009-06-27 Fix wrong-type error no such file. Renamed faces. Add: *-prop-set.
+;; Load gnus at compile time. Protect tramp-file-name-regexp with boundp.
+;; 2009-06-25 Fixes for older Emacs compatibility.
+;; 2009-06-24 Improve *-default-handler.
+;; Add: *-always-save-relocated-position, *-prop-get.
+;; 2009-06-23 Use search-regexp, not re-search-regexp. Add Gnus bmks. Add doc.
+;; Fix *-bmenu-list.
+;; 2009-06-21 Fix: *-default-handler for Info. Improve doc strings, commentary.
+;; Fixes to be compatible with Emacs 20-22.
+;; Use defcustom for *-list-only-regions-flag.
+;; *jump: Put prefix arg in interactive spec. Use buffer-name, not buffer.
+;; Remove require of Tramp and inline Tramp fns.
+;; Remove tests for display-(color|mouse)-p.
+;; w3m-bookmark-(jump|make-record): require w3m.
+;; 2009-06-20 Update context strings when relocate.
+;; Fix: bookmark-get-*: search from point-min.
+;; 2009-06-19 Fix: *-make-record-default, *-toggle-use-only-regions, *-default-handler,
+;; bookmarking Dired.
+;; Handle 4 positions in *-default-handler.
+;; 2009-06-17 Fix: case where some bookmarked text was removed, *-use-region.
+;; 2009-06-15 Fix *-region-alist-only, *-get-buffername, *-location,
+;; non-file (buffer) bookmarks.
+;; Support w3m similar to Info.
+;; 2009-06-14 Fix bookmark+version, region relocation. Info support. Error handling.
+;; 2009-06-13 Fix: *-list-only-regions, *-region-handler, *-make-record, keymap, faces.
+;; Put region & info handling in *-default-handler, not separate handlers.
+;; Merge *-make-record-region to *-make-record-default.
+;; *-jump now negates *-use-region if prefix arg. Raise error if bad bmk.
+;; 2009-06-12 Add: *-get-endposition, *-region-alist-only-names.
+;; Add filter to show only region bookmarks.
+;; Faces for menu list. Change region color.
+;; 2009-06-11 Add: *-region-search-size, *-get-buffername, *-use-region.
+;; Redefine *-handle-bookmark, *-jump, to fit bookmark-use-region.
+;; Add condtions to bookmark-make-record. Support w3m. Support t command.
+;; 2009-06-10 Fix search regexp. Fix region in Info. Save bookmark if region moves.
+;; 2009-06-09 Added: bookmark-make-record(-region), bookmark-region-handler.
+;; Relocation.
+;; 2009/05/25 dadams
+;; Added redefinition of bookmark-get-bookmark-record.
+;; 2008/10/16 dadams
+;; bookmark-jump-other-window: Don't define it for Emacs 23+ (not needed).
+;; 2008/04/04 dadams
+;; bookmark-jump-other-window: Updated wrt Emacs 22.2.
+;; 2007/10/07 dadams
+;; Added: bookmark-completing-read, bookmark-delete, bookmark-insert(-location),
+;; bookmark-jump, bookmark-relocate, bookmark-rename.
+;; bookmark-jump-other-window: Use new bookmark-completing-read.
+;; 2007/07/13 dadams
+;; Replaced Emacs version tests to reflect Emacs 22 release.
+;; 2006/03/08 dadams
+;; bookmark-jump-other-window: Handle nil arg.
+;; 2005/05/17 dadams
+;; Updated to work with Emacs 22.x.
+;; 2004/11/20 dadams
+;; Refined to deal with Emacs 21 < 21.3.50 (soon to be 22.x)
+;; 2004/10/26 dadams
+;; Different menu-bar command, depending on Emacs version.
+;; 2004/09/21 dadams
+;; Only define bookmark-menu-jump-other-window if < Emacs 22.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;; You need not load this file. It contains only documentation.
+
+(provide 'bookmark+-chg) ; Not used.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; bookmark+-chg.el ends here
--- /dev/null
+;;; bookmark+-doc.el - Documentation for package Bookmark+.
+;;
+;; Filename: bookmark+-doc.el
+;; Description: Documentation for package Bookmark+
+;; Author: Drew Adams
+;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com")
+;; Copyright (C) 2000-2022, Drew Adams, all rights reserved.
+;; Created: Fri Sep 15 07:58:41 2000
+;; Last-Updated: Fri Jan 14 12:46:47 2022 (-0800)
+;; By: dradams
+;; Update #: 15385
+;; URL: https://www.emacswiki.org/emacs/download/bookmark%2b-doc.el
+;; Doc URL: https://www.emacswiki.org/emacs/BookmarkPlus
+;; Keywords: bookmarks, bookmark+, placeholders, annotations, search,
+;; info, url, eww, w3m, gnus
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x, 26.x
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Documentation for the Bookmark+ package, which provides
+;; extensions to standard library `bookmark.el'.
+;;
+;; The Bookmark+ libraries are these:
+;;
+;; `bookmark+.el' - main (driver) library
+;; `bookmark+-mac.el' - Lisp macros
+;; `bookmark+-lit.el' - (optional) code for highlighting bookmarks
+;; `bookmark+-bmu.el' - code for the `*Bookmark List*' (bmenu)
+;; `bookmark+-1.el' - other required code (non-bmenu)
+;; `bookmark+-key.el' - key and menu bindings
+;;
+;; `bookmark+-doc.el' - documentation (comment-only - this file)
+;; `bookmark+-chg.el' - change log (comment-only file)
+;;
+;; The documentation includes how to byte-compile and install
+;; Bookmark+. It is also available in these ways:
+;;
+;; 1. From the bookmark list (`C-x x e' or `C-x r l'):
+;; Use `?' to show the current bookmark-list status and general
+;; help, then click link `Doc in Commentary' or link `Doc on the
+;; Web'.
+;;
+;; 2. From the Emacs-Wiki Web site:
+;; https://www.emacswiki.org/emacs/BookmarkPlus.
+;;
+;; 3. From the Bookmark+ group customization buffer:
+;; `M-x customize-group bookmark-plus', then click link
+;; `Commentary'.
+;;
+;; (The commentary links in #1 and #3 work only if put you this
+;; library, `bookmark+-doc.el', in your `load-path'.)
+;;
+;; More Bookmark+ description below.
+;;
+;; To report Bookmark+ bugs: `M-x customize-group bookmark-plus'
+;; and then follow (e.g. click) the link `Send Bug Report', which
+;; helps you prepare an email to me.
+;;
+;;
+;; ****** NOTE ******
+;;
+;; On 2010-06-18, I changed the prefix used by package Bookmark+
+;; from `bookmarkp-' to `bmkp-'. THIS IS AN INCOMPATIBLE CHANGE.
+;; I apologize for the inconvenience, but the new prefix is
+;; preferable for a number of reasons, including easier
+;; distinction from standard `bookmark.el' names.
+;;
+;; This change means that YOU MUST MANUALLY REPLACE ALL
+;; OCCURRENCES of `bookmarkp-' by `bmkp-' in the following
+;; places, if you used Bookmark+ prior to this change:
+;;
+;; 1. In your init file (`~/.emacs') or your `custom-file', if
+;; you have one. This is needed if you customized any
+;; Bookmark+ features.
+;;
+;; 2. In your default bookmark file, `bookmark-default-file'
+;; (`~/.emacs.bmk'), and in any other bookmark files you might
+;; have.
+;;
+;; 3. In your `*Bookmark List*' state file,
+;; `bmkp-bmenu-state-file' (`~/.emacs-bmk-bmenu-state.el').
+;;
+;; 4. In your `*Bookmark List*' commands file,
+;; `bmkp-bmenu-commands-file' (`~/.emacs-bmk-bmenu-commands.el'),
+;; if you have one.
+;;
+;; You can do this editing in a virgin Emacs session (`emacs
+;; -Q'), that is, without loading Bookmark+.
+;;
+;; Alternatively, you can do this editing in an Emacs session
+;; where Bookmark+ has been loaded, but in that case you must
+;; TURN OFF AUTOMATIC SAVING of both your default bookmark file
+;; and your `*Bookmark List*' state file. Otherwise, when you
+;; quit Emacs your manually edits will be overwritten.
+;;
+;; To turn off this automatic saving, you can use `M-~' and
+;; `C-M-~' in buffer `*Bookmark List*' (commands
+;; `bmkp-toggle-saving-bookmark-file' and
+;; `bmkp-toggle-saving-menu-list-state' - they are also in the
+;; `Bookmark+' menu).
+;;
+;; Again, sorry for this inconvenience.
+
+;;(@> "Index")
+;;
+;; Index
+;; -----
+;;
+;; If you have library `linkd.el' and Emacs 22 or later, load
+;; `linkd.el' and turn on `linkd-mode' now. It lets you easily
+;; navigate around the sections of this doc. Linkd mode will
+;; highlight this Index, as well as the cross-references and section
+;; headings throughout this file. You can get `linkd.el' here:
+;; https://www.emacswiki.org/emacs/download/linkd.el.
+;;
+;; (@> "Documentation")
+;; (@> "Installing Bookmark+")
+;; (@> "Bookmark+ Load Order and Option `bookmark-default-file'")
+;; (@> "Bookmark+ Features")
+;; (@> "Bookmark Basics")
+;; (@> "Different Types of Jump Commands")
+;; (@> "Bookmark Annotations")
+;; (@> "Bookmark Tags")
+;; (@> "Bookmark Tags Can Have Values")
+;; (@> "Hierarchical Structures of Bookmarks?")
+;; (@> "Function, Sequence, Variable-List,... Bookmarks")
+;; (@> "Little Persistent Named Nothings")
+;; (@> "Editing Bookmarks")
+;; (@> "Bookmark Records: What A Bookmark Looks Like")
+;; (@> "Bookmark-List Views - Saving and Restoring State")
+;; (@> "Quitting Saves the Bookmark-List State")
+;; (@> "State-Restoring Commands and Bookmarks")
+;; (@> "Bookmarking without Visiting the Target")
+;; (@> "Bookmarking a File or a URL")
+;; (@> "Bookmarking the Marked Files in Dired")
+;; (@> "Bookmarking Compilation, Grep, and Occur Hits")
+;; (@> "Bookmarking Files That You Cannot Visit with Emacs")
+;; (@> "Opening Bookmarks Using Windows File Associations")
+;; (@> "Autofile Bookmarks")
+;; (@> "A Type-Aware `find-file'")
+;; (@> "Tagging Files")
+;; (@> "Using Multiple Bookmark Files")
+;; (@> "Bookmark-File Bookmarks")
+;; (@> "The Bookmark List Display")
+;; (@> "Jumping To Bookmarks from the Bookmark List Display")
+;; (@> "Tag Commands and Keys")
+;; (@> "Tags: Sets of Bookmarks")
+;; (@> "Open Dired for the Marked File Bookmarks")
+;; (@> "Marking and Unmarking Bookmarks")
+;; (@> "Filtering Bookmarks (Hiding and Showing)")
+;; (@> "Only Visible Bookmarks Are Affected")
+;; (@> "Omitting Bookmarks from Display")
+;; (@> "Sorting Bookmarks")
+;; (@> "Bookmarks for Specific Files or Buffers")
+;; (@> "Cycling, Navigation List")
+;; (@> "The Bookmark Navigation List")
+;; (@> "Cycling the Navigation List")
+;; (@> "Cycling Dynamic Sets of Bookmarks")
+;; (@> "Cycling in the Current File/Buffer")
+;; (@> "Autonamed Bookmarks - Easy Come Easy Go")
+;; (@> "Temporary Bookmarks")
+;; (@> "Temporary Bookmarking Mode")
+;; (@> "Making Bookmarks Temporary")
+;; (@> "Automatic Bookmarking")
+;; (@> "Automatic Bookmarking Using a Hook")
+;; (@> "Automatic Idle-Period Bookmarking")
+;; (@> "Automatic Info Bookmarking")
+;; (@> "Highlighting Bookmark Locations")
+;; (@> "Defining How to Highlight")
+;; (@> "Highlighting On Demand")
+;; (@> "Highlighting Automatically")
+;; (@> "Using Highlighted Bookmarks")
+;; (@> "Bookmark Links")
+;; (@> "Org Mode Links that Jump To Bookmarks")
+;; (@> "Bookmark Menus")
+;; (@> "Use Bookmark+ with Icicles")
+;; (@> "Bookmark Compatibility with Vanilla Emacs (`bookmark.el')")
+;; (@> "New Bookmark Structure")
+
+;;(@* "Documentation")
+;;
+;; Documentation
+;; -------------
+;;
+;;(@* "Installing Bookmark+")
+;; ** Installing Bookmark+ **
+;;
+;; The main Bookmark+ library is `bookmark+.el'. The other required
+;; libraries are `bookmark+-mac.el', `bookmark+-bmu.el',
+;; `bookmark+-1.el', and `bookmark+-key.el'. If you want to be able
+;; to highlight bookmarks then you will also need library
+;; `bookmark+-lit.el'. I recommend that you byte-compile all of the
+;; libraries, after loading the source files (in particular, load
+;; `bookmark+-mac.el').
+;;
+;; Put the directory of these libraries in your `load-path' and add
+;; this to your init file (~/.emacs):
+;;
+;; (require 'bookmark+)
+;;
+;; That will load all of the Bookmark+ libraries. If you do not care
+;; about bookmark highlighting then simply do not put
+;; `bookmark+-lit.el' in your `load-path'.
+;;
+;; By default (see option `bmkp-crosshairs-flag'), when you visit a
+;; bookmark that has no region it is highlighted temporarily using
+;; crosshairs, for easy recognition. (This temporary highlighting is
+;; independent of the highlighting provided by `bookmark+-lit.el'.)
+;;
+;; For this optional crosshairs feature you also need library
+;; `crosshairs.el', which in turn requires libraries `col-highlight',
+;; `hl-line', `hl-line+', and `vline'. Library `hl-line' comes with
+;; vanilla Emacs. The others are available from the Emacs Wiki web
+;; site: https://www.emacswiki.org/. You also need Emacs 22 or later
+;; for this feature.
+;;
+;;
+;;(@* "Bookmark+ Load Order and Option `bookmark-default-file'")
+;; *** Bookmark+ Load Order and Option `bookmark-default-file' ***
+;;
+;; Standard option `bookmark-default-file' defines the default
+;; location of your bookmark file. Bookmark+ does not change the
+;; value. You can change the value, of course, either by customizing
+;; it (recommended) or using Lisp code (including in your init file).
+;;
+;; However, the value of `bookmark-default-file' is used when you
+;; load Bookmark+ to initialize some other variables, in particular
+;; option `bmkp-last-as-first-bookmark-file' and internal variable
+;; `bmkp-current-bookmark-file'.
+;;
+;; This means that if you modify `bookmark-default-file' in your init
+;; file, and you want your new value to be take into account by
+;; Bookmark+, then modify it before you load Bookmark+.
+;;
+;; Be aware also that another library that you load might, itself,
+;; load Bookmark+, in which case you will for the same reason want to
+;; load that library after you have modified `bookmark-default-file'.
+;; An example of this is Icicles, which loads Bookmark+ if Bookmark+
+;; is in your `load-path'.
+;;
+;; In general, with Bookmark+ I recommend that you simply set option
+;; `bookmark-default-file' once and for all at the outset, preferably
+;; by customizing it. You can use `bmkp-switch-bookmark-file-create'
+;; at any time to switch to a different bookmark file - it is bound
+;; to `C-x x L'. You can also invoke it in your init file, provided
+;; Bookmark+ has already been loaded.
+;;
+;; See Also: (@> "Using Multiple Bookmark Files")
+
+;;(@* "Bookmark+ Features")
+;; ** Bookmark+ Features **
+;;
+;; Here is an overview of some of the features that Bookmark+
+;; provides. Some of these are detailed in other sections, below.
+;;
+;; * Richer bookmarks. They record more. They are more accurate.
+;;
+;; - An optional bookmark annotation is user-supplied text that is
+;; saved as part of the bookmark. You can use any text you
+;; like, and you can use it for any purpose you like. In
+;; Bookmark+, the mode for viewing and editing a bookmark
+;; annotation is Org mode, by default.
+;;
+;; - In addition, Bookmark+ lets you optionally use a separate
+;; file, URL, or bookmark to annotate any bookmark. Accessing
+;; ("showing") such an external annotation visits its
+;; destination. So for example, you can use bookmarks to one or
+;; more Org files to annotate one or more bookmarks. The
+;; annotation saved with the bookmark itself just specifies the
+;; destination. See (@> "Bookmark Annotations").
+;;
+;; - You can tag bookmarks, a la del.icio.us. In effect, tags
+;; define bookmark sets. A bookmark can have any number of
+;; tags, and multiple bookmarks can have the same tag. You can
+;; sort, show/hide, or mark bookmarks based on their tags.
+;;
+;; - Bookmark+ tags can be more than just names. They can be
+;; full-fledged user-defined attributes, with Emacs-Lisp objects
+;; as their values.
+;;
+;; - You can have multiple bookmarks with the same name. This is
+;; particularly useful for autofile bookmarks, which are
+;; bookmarks that have the same name as their target files or
+;; directories. They give you the effect of using files or
+;; directories themselves as bookmarks. In particular, they let
+;; you, in effect, tag files and directories.
+;; See (@> "Autofile Bookmarks") and (@> "Tagging Files").
+;;
+;; (In vanilla Emacs you can also, in theory, have multiple
+;; bookmarks with the same name. But you cannot really use them
+;; in any practical way. Vanilla Emacs cannot distinguish among
+;; them: the most recent one shadows all others with the same
+;; name.)
+;;
+;; - Bookmarks record the number of times you have visited them
+;; and the time of the last visit. You can sort, show/hide, or
+;; mark bookmarks based on this info.
+;;
+;; - You can combine bookmarks, to make composite, or sequence,
+;; bookmarks. Invoking a sequence bookmark invokes each of its
+;; component bookmarks in turn. A component bookmark can itself
+;; be a sequence bookmark.
+;;
+;; - You can bookmark a region of text, not just a position. When
+;; you jump to a bookmark that records a region, the region is
+;; activated (see option `bmkp-use-region'). (Region activation
+;; is not supported for Gnus bookmarks.)
+;;
+;; You can define your own region handler for bookmarks that
+;; record regions. (This is in addition to being able to define
+;; bookmark handlers.) Use option `bmkp-handle-region-function'
+;; for this. As one example, command
+;; `bmkp-region-jump-narrow-indirect-other-window' binds the
+;; option to a function that narrows the targeted region in a
+;; cloned indirect buffer. (You need library
+;; `narrow-indirect.el' for this command.)
+;;
+;; - Bookmarks are relocated better than for vanilla Emacs when
+;; the contextual text changes.
+;;
+;; * Additional ways to bookmark.
+;;
+;; - You can bookmark the file or URL named at point (or any other
+;; file or URL), without first visiting it.
+;;
+;; - You can bookmark the targets of the hits in a compilation
+;; buffer or an `occur' buffer, without first visiting them.
+;;
+;; - You can bookmark all of the marked files in Dired at once.
+;;
+;; * Additional types of bookmarks.
+;;
+;; Bookmark+ adds over 70 types of bookmark. (You can see what they
+;; all are by invoking function `bmkp-types-alist'.) Here are the
+;; main ones:
+;;
+;; - Autofile bookmarks. You can bookmark a file without visiting
+;; it or naming the bookmark. The bookmark name is the same as
+;; the file name (nondirectory part). You can have multiple
+;; such bookmarks with the same name, to bookmark files with the
+;; same name but in different directories.
+;;
+;; - Dired bookmarks. You can bookmark a Dired buffer, recording
+;; and restoring its `ls' switches, which files are marked,
+;; which subdirectories are inserted, and which (sub)directories
+;; are hidden.
+;;
+;; - Dired-tree bookmarks. A set of Dired bookmarks that
+;; represent a directory hierarchy and are opened together.
+;;
+;; - Bookmark-list bookmarks. You can bookmark the current state
+;; of buffer `*Bookmark List*' - a list of bookmarks. Jumping
+;; to such a bookmark restores the recorded sort order,
+;; markings, filter, title, and omit list.
+;; See (@> "Omitting Bookmarks from Display").
+;;
+;; - Bookmark-file bookmarks. You can bookmark a bookmark file.
+;; Jumping to such a bookmark loads the bookmarks in the file.
+;; See (@> "Bookmark-File Bookmarks").
+;;
+;; - Desktop bookmarks. You can bookmark the current Emacs
+;; desktop, as defined by library `desktop.el' - use command
+;; `bmkp-set-desktop-bookmark' (`C-x x K'). You can "jump" to a
+;; desktop bookmark (that is, restore its saved desktop). A
+;; desktop includes:
+;;
+;; - Some global variables. To exclude variables normally
+;; saved, see option `bmkp-desktop-no-save-vars'.
+;; - The current set of buffers and their associated files.
+;; For each: its mode, point, mark, & some local variables.
+;;
+;; If option `bmkp-desktop-jump-save-before-flag' is non-`nil',
+;; and if the current desktop was made current by jumping to a
+;; bookmark, then it is saved before jumping to the next
+;; desktop. If you want to save the last desktop jumped to when
+;; you quit Emacs, then add `bmkp-desktop-save-as-last' to
+;; `kill-emacs-hook'.
+;;
+;; - Gnus bookmarks. You can bookmark a Gnus article, a URL, a
+;; PDF file (DocView), a UNIX manual page (from the output of
+;; Emacs command `man' or `woman'), an image, or a piece of
+;; music.
+;;
+;; - Non-file (buffer) bookmarks. You can bookmark a buffer that
+;; is not associated with a file.
+;;
+;; - Function bookmarks. A bookmark can represent a Lisp
+;; function, which is invoked when you "jump" to the bookmark.
+;;
+;; - Sequence (composite) bookmarks. A bookmark can represent a
+;; sequence of other bookmarks.
+;;
+;; - Keyboard-macro bookmarks, bookmarks for sets of keyboard
+;; macros, and sequence bookmarks that combine another bookmark
+;; with a keyboard macro.
+;;
+;; - Lisp variable bookmarks. A bookmark can represent a set of
+;; variables and their values.
+;;
+;; - Snippet bookmarks. Select some some text and give it a
+;; (bookmark) name. Then copy it to the `kill-ring' anytime, in
+;; any Emacs session.
+;;
+;; - Icicles search-hits bookmarks. (You need library Icicles to
+;; use this feature.) During Icicles search you can use `C-x
+;; C-M->' to save the current set of completion candidates
+;; (search hits matching your current input) as an Icicles
+;; search-hits bookmark. During a later Icicles search you can
+;; retrieve those search hits saved in the bookmark, by using
+;; `C-x C-M-<`. You can add to (instead of replacing) the
+;; current set of hits with hits retrieved from a bookmark using
+;; `C-x C-<'. This is the only way you can "jump" to such a
+;; bookmark.
+;;
+;; In particular, note that you can use the following kinds of
+;; bookmarks to quickly switch among different projects (sets of
+;; bookmarks): Dired, Dired tree, bookmark-list, bookmark-file,
+;; and desktop bookmarks.
+;;
+;; * Type-specific jump commands.
+;;
+;; - When you want to jump to a bookmark of a specific type
+;; (e.g. Dired), you can use a command that offers only such
+;; bookmarks as completion candidates.
+;;
+;; - You can also use generic command `bmkp-jump-to-type', bound
+;; to `C-x j :'. It prompts you for the bookmark type, then
+;; offers only bookmarks of that type as completion candidates.
+;;
+;; * Define your own new bookmark types.
+;;
+;; Just as for vanilla Emacs, you can easily define your own
+;; bookmark types, by defining a function to create its record,
+;; using function `bookmark-make-record', or by binding variable
+;; `bookmark-make-record-function' for a given context.
+;;
+;; But you can also make jumping to a new type of bookmarks
+;; type-specific, usable with `bmkp-jump-to-type' (`C-x j :') or
+;; with your own type-specific jump command.
+;;
+;; For that, just:
+;;
+;; 1. Define a function `bmkp-TYPE-alist-only', which returns an
+;; alist of bookmarks that are only of your new TYPE, for use
+;; with `bookmark-completing-read'. The alist should have the
+;; same form as `bookmark-alist'. (And you can use your alist
+;; for more than just completion.)
+;;
+;; 2. Evaluate `(bmkp-define-history-variables)', to add a history
+;; variable for your type, again, for use with
+;; `bookmark-completing-read'.
+;;
+;; * Extensive menus.
+;;
+;; - In the `*Bookmark List*' display, a `mouse-3' popup menu has
+;; actions for the individual bookmark that you point to when
+;; you click the mouse.
+;;
+;; - In the `*Bookmark List*' display, a complete menu-bar menu,
+;; `Bookmark+', is available. The same menu is available on
+;; `C-mouse-3'. It has submenus `Jump To', `Mark', `Omit',
+;; `Show', `Sort', `Tags', `Highlight' (needs library
+;; `bookmark+-lit.el), and `Define Command'.
+;;
+;; - The vanilla `Bookmarks' menu, which is typically a submenu of
+;; the menu-bar `Edit' menu, is modified by adding several items
+;; from the `Bookmark+' menu, including submenus `Jump To',
+;; `Tags', and `Highlight'.
+;;
+;; - Bookmark+ adds two items to the menu bar `Edit' menu:
+;;
+;; . Save the active region text as a bookmark.
+;; . Jump to the bookmark to copy the text to the kill ring, so
+;; you can then yank it anywhere.
+;;
+;; - Some modes provide a `Bookmarks Here' menu-bar submenu with
+;; items to access bookmarks for the current file/buffer.
+;; Display of this menu is controlled by option
+;; `bmkp-add-bookmarks-here-menu-flag' (`nil' by default
+;; because computing the menu can take a little time).
+;;
+;; * Improvements for the bookmark-list display.
+;;
+;; This is buffer `*Bookmark List*', aka the bookmark "menu list"
+;; (a misnomer), which you display using `C-x x e' (or `C-x r l').
+;; See (@> "The Bookmark List Display").
+;;
+;; - The last display state is saved (by default), and is restored
+;; the next time you show the list. (Tip: Use the bookmark list
+;; as your "Home" page at Emacs startup.)
+;;
+;; - You can save the current bookmark-list state at any time and
+;; return to it later. There are a few ways to do this,
+;; including bookmarking the list itself.
+;; See (@> "Bookmark-List Views - Saving and Restoring State").
+;;
+;; - Marking/unmarking is enhanced. It is similar to Dired's.
+;;
+;; - You can easily mark or show different classes of bookmarks.
+;;
+;; - Faces distinguish bookmarks by type.
+;;
+;; - You can sort bookmarks in many ways. You can easily define
+;; your own sort orders, even complex ones.
+;;
+;; - You can regexp-search (`M-a') or query-replace (`M-q') the
+;; targets (destination file or buffers) of the marked
+;; bookmarks, in the current bookmark-list sort order. For
+;; Emacs 23 and later, you can even search incrementally (`M-s a
+;; C-s', or `M-s a C-M-s' for regexp).
+;;
+;; - You can use `M-d >' to open Dired for just the local file
+;; bookmarks that are marked (`>').
+;;
+;; - If you use Emacs on Microsoft Windows, you can open bookmarks
+;; according to Windows file associations. (You will also need
+;; library `w32-browser.el'.)
+;;
+;; - You can use (lax) completion when you set a bookmark using
+;; `C-x r m' (`bmkp-bookmark-set-confirm-overwrite'), choosing
+;; from existing bookmarks for the same buffer. This makes it
+;; easy to update a nearby bookmark (e.g. relocate it). With a
+;; numeric prefix argument (or if there are no bookmarks for the
+;; buffer), you can choose from all bookmarks.
+;;
+;; - You can edit a bookmark: its name and file name/location, its
+;; tags, or its complete defining internal Lisp record.
+;;
+;; - The mode line shows the number of bookmarks that are marked
+;; (`>'), flagged for deletion (`D'), tagged (`t'), temporary
+;; (`X'), annotated (`a'), and modified (unsaved) (`*'). It
+;; also shows the current sort order.
+;;
+;; For each of the number indicators (e.g., the number marked):
+;;
+;; If the current line has the indicator (e.g. `>') and there
+;; are other lines with the same indicator that are listed after
+;; the current line, then the indicator shows `N/M', where N is
+;; the number indicated through the current line and M is the
+;; total number indicated. Otherwise, it shows just `N'.
+;;
+;; This feature is available starting with Emacs 24.3. (For
+;; prior versions I removed it because Emacs bug #12867 can
+;; cause Emacs to crash.)
+;;
+;; * Multiple bookmark files.
+;;
+;; - Although vanilla Emacs lets you load different bookmark
+;; files, it does not support this feature well, and the
+;; behavior can even be contradictory. With Bookmark+ you can
+;; easily (a) switch among alternative bookmark files or (b)
+;; load multiple files into the same session, accumulating their
+;; bookmark definitions. The last file you used is the default
+;; when you choose a file to switch to, so it is easy to go back
+;; and forth between two bookmark files.
+;; See (@> "Using Multiple Bookmark Files").
+;;
+;; * Dedicated keymaps as prefix keys.
+;;
+;; - Prefix `C-x x' is used for bookmark keys, in general. The
+;; vanilla keys on prefix `C-x r' are still available also, but
+;; that prefix is shared with register commands, making it less
+;; convenient for bookmarks. Using `C-x x' lets you focus on
+;; bookmarks.
+;;
+;; - Prefix `C-x x c' is for setting various kinds of bookmarks.
+;;
+;; - Prefixes `C-x j' and `C-x 4 j' (for other-window) are used
+;; for bookmark jump commands. Again, a dedicated prefix key
+;; helps you focus on one kind of action (jumping).
+;;
+;; All of these prefix keys correspond to prefix-map variables, so
+;; you need not use these particular prefixes. You can bind these
+;; maps to any prefix keys you want. These are the maps, together
+;; with their predefined bindings.
+;;
+;; `bookmark-map' - `C-x x'
+;; `bmkp-set-map' - `C-x x c'
+;; `bmkp-tags-map' - `C-x x t'
+;; `bmkp-jump-map' - `C-x j'
+;; `bmkp-jump-other-window-map' - `C-x 4 j'
+;;
+;; Those are the prefix keys that are available by default. To
+;; change them, just customize these user options, each of which
+;; is a list of the key sequences to use as prefix key.
+;;
+;; - `bmkp-bookmark-map-prefix-keys' - default: ("^Xp")
+;; - `bmkp-jump-map-prefix-keys' - default: ("^Xj")
+;; - `bmkp-jump-other-window-map-prefix-keys' - default: ("^X4j")
+;;
+;; (`^X' here is actually the Control-X character.)
+;;
+;; Keymaps `bmkp-set-map' and `bmkp-tags-map' are always on
+;; `bookmark-map', whatever prefix keys it is on. So if, for
+;; example, you customize `bmkp-bookmark-map-prefix-keys' to be
+;; ("^Xp" [f9]) then the keys in `bmkp-set-map' have both prefix
+;; `C-x x c' and prefix `<f9> c'.
+;;
+;; In addition to keys on Bookmark+ keymaps, Bookmark+ binds some
+;; mode-specific bookmarking commands in some other modes: Occur,
+;; Compilation (including Grep), Buffer-menu, EWW, Gnus, Info,
+;; Man, Woman, W3M, and Dired (if you use library `Dired+').
+;; These keys let you set or jump to bookmarks specific to the
+;; modes.
+;;
+;; * Helpful help.
+;;
+;; - Information about individual bookmarks.
+;;
+;; . Anywhere in Emacs, `C-x h M' (command
+;; `bmkp-describe-bookmark') describes any bookmark. With a
+;; prefix argument, it shows you the full information that
+;; defines it (internal form).
+;;
+;; . With the cursor on a highlighted bookmark, `C-x x ?' shows
+;; the same description, and a prefix argment has the same
+;; effect (show internal form).
+;;
+;; . Hovering your mouse over a highlighted bookmark shows the
+;; same description, in a tooltip. Actually, you can
+;; customize the description using option
+;; `bmkp-tooltip-content-function'. The default value is
+;; `bmkp-bookmark-description', which describes the bookmark.
+;; A value of `bmkp-annotation-or-bookmark-description', for
+;; example, shows the bookmark annotation if there is one, or
+;; the full description if not.
+;;
+;; . In the bookmark list, `C-h RET' (or `C-h C-RET') describes
+;; the bookmark under the cursor. The description is as
+;; complete as possible - for example, for an image-file
+;; bookmark the complete EXIF image metadata is shown. (This
+;; is only for Emacs 22 and later, and only if you have
+;; command-line tool `exiftool' installed. See standard Emacs
+;; library `image-dired.el' for more information about
+;; `exiftool'.)
+;;
+;; And again, a prefix arg (`C-u C-h RET') means show the full
+;; (internal) bookmark information.
+;;
+;; `C-h >' shows the same information that `C-h RET' shows,
+;; but for all of the marked bookmarks, in the current sort
+;; order. That is, it describes each of the marked bookmarks.
+;;
+;; `C-down' and `C-up' move the cursor down and up a line,
+;; respectively, but they also show the description of the
+;; bookmark corresponding to the new cursor location. This is
+;; a quick way to cycle among bookmark descriptions, in the
+;; current sort order.
+;;
+;; - General Bookmark+ documentation.
+;;
+;; . Anywhere in Emacs, `M-x bmkp-bmenu-mode-status-help' shows
+;; detailed information about the current state of the
+;; bookmark list. Click button `Doc in Commentary' or button
+;; `Doc on the Web' to access the complete documentation.
+;;
+;; (Use button `Customize' to customize all Bookmark+
+;; faces and options.)
+;;
+;; . In the bookmark list, `?' and `C-h m' are the same as `M-x
+;; bmkp-bmenu-mode-status-help'. (`C-h m' in the bookmark
+;; list does not show you info about minor modes. If you want
+;; that, use `M-x describe-mode'.)
+;;
+;; . In the `bookmark-plus' group customization buffer (`M-x
+;; customize-group bookmark-plus'), click button `Commentary'.
+;;
+;; . From the Emacs-Wiki Web site,
+;; https://www.emacswiki.org/emacs/BookmarkPlus.
+;;
+;; - It is easy to recognize orphaned and invalid bookmarks.
+;;
+;; . Invalid bookmarks are shown in a special face in the
+;; bookmark-list display.
+;;
+;; . You can easily mark all of the orphaned bookmarks, that is,
+;; those whose recorded files have been renamed or deleted.
+;; You can then relocate or delete those bookmarks.
+;;
+;; - It is easy to recognize modified (i.e., unsaved) bookmarks.
+;; They are marked with `*'. Likewise, bookmarks that have tags
+;; (marked with `t'); bookmarks that have annotations (`a'); and
+;; bookmarks that are temporary (`X'), meaning that they will
+;; not be saved.
+;;
+;; * Jump-destination highlighting.
+;;
+;; - When you jump to a bookmark, the destination (position) is
+;; highlighted temporarily using crosshairs, to make it stand
+;; out. Option `bmkp-crosshairs-flag' controls this, and this
+;; feature is available only if you also use library
+;; `crosshairs.el'.
+;;
+;; * Visual bookmarks (highlighting).
+;;
+;; - You can highlight the locations of bookmarks, either
+;; automatically or on demand. You control what kind of
+;; highlighting, if any, is used for which bookmarks. This
+;; feature requires that you have library `bookmark+-lit.el' in
+;; your `load-path' (it will then be loaded by `bookmark+.el).
+;;
+;; * Better, user-configurable bookmark-name defaults.
+;;
+;; See the doc strings of command `bookmark-set' (Bookmark+
+;; version) and options `bmkp-new-bookmark-default-names' and
+;; `bmkp-default-bookmark-name'.
+;;
+;; * Synergy with `Icicles'.
+;;
+;; - `Icicles' works with Bookmark+ to provide enhanced bookmark
+;; jumping (visiting), setting, and help. It gives you a
+;; bookmark browser, and lets you bookmark and tag files on the
+;; fly. See (@> "Use Bookmark+ with Icicles") and
+;; https://www.emacswiki.org/emacs/Icicles.
+
+;;(@* "Bookmark Basics")
+;; ** Bookmark Basics **
+;;
+;; Bookmark+ builds on vanilla Emacs bookmarks. If you are familiar
+;; with the latter, then you can skip this section, which mostly
+;; reviews the former. However, this section also introduces some
+;; Bookmark+ concepts and features that are detailed in other
+;; sections.
+;;
+;; In Emacs bookmarking these three things are different but related:
+;;
+;; 1. the bookmark list
+;; 2. the bookmark file
+;; 3. the bookmark-list display (buffer `*Bookmark List*', aka the
+;; bookmark "menu list", a misnomer)
+;;
+;; It is important to keep these three straight and understand their
+;; differences in practice, in particular, when they do and do not
+;; represent the same set of bookmarks.
+;;
+;; #1 is in memory. It is the current set of bookmarks. When you
+;; add, rename, delete, etc. a bookmark, this list is updated.
+;;
+;; #2 is on disk. It is a persistent record of a set of bookmarks.
+;;
+;; The bookmark list (#1) is the current value of internal variable
+;; `bookmark-alist'. The bookmark file (#2) can be anywhere. Its
+;; default filename is the value of user option
+;; `bookmark-default-file'.
+;;
+;; The bookmark list is typically initialized from the bookmark file
+;; - referred to as loading your bookmarks, but you can also create
+;; bookmarks (adding them to the list) without ever saving them to
+;; disk.
+;;
+;; The bookmark list can be saved to the bookmark file - referred to
+;; as saving your bookmarks - either automatically or on demand. But
+;; it is not necessarily saved. Even if it has been saved in the
+;; past, that does not mean that at any given time the bookmark list
+;; corresponds exactly to the bookmark file.
+;;
+;; The list and the file can often become out of sync. In an Emacs
+;; session, the bookmark list rules. After an Emacs session, the
+;; bookmark file rules (it is all there is). You can use `C-x x L'
+;; (`bmkp-switch-bookmark-file-create') to sync (revert) the list to
+;; reflect the file - just accept the default value, "switching" to
+;; the same file.
+;;
+;; The bookmark-list display (#3) is a snapshot view of the bookmarks
+;; in the bookmark list. As such, what you see there reflects the
+;; state of the bookmark list at some point in time. So here again,
+;; the two, list and display, can be out of sync. Hitting `g' in the
+;; bookmark-list display refreshes it to accurately reflect the
+;; current bookmark list (#1). Some other operations in the display
+;; also keep it synced with the list.
+;;
+;; Using a prefix argument (`C-u g') syncs the display (#3) and the
+;; list (#1) to the file (#2). This can be useful when some other
+;; process (e.g., another Emacs session) updates the bookmark file or
+;; when you want to abandon changes to the current bookmark list and
+;; any of the current bookmarks. Outside the bookmark-list display,
+;; you can use command `bmkp-revert-bookmark-file' to do this.
+;;
+;; You can load different bookmark files, either adding their
+;; bookmarks to those already in the current bookmark list or
+;; replacing them.
+;;
+;; The most important takeaway from this section is that #1 (list),
+;; #2 (file), and #3 (display) can be out of sync, and they often
+;; are. And that can be useful.
+;;
+;; Until now, everything said in this section is true of vanilla
+;; Emacs as well as Bookmark+. Bookmark+ adds some flexibility
+;; regarding the use of multiple bookmark files, and it can save the
+;; last state of the bookmark-list display for later reuse.
+;;
+;; The saved state of the display is restored when you show the
+;; display after quitting it (`q') in the same session or quitting
+;; Emacs, but only if the bookmark file whose location it recorded is
+;; the same as the current bookmark file.
+;;
+;; It would not make sense to display a completely different set of
+;; bookmarks from those that are currently loaded. The display must
+;; always reflect the current bookmark list (even if it sometimes
+;; reflects it imperfectly, because it is a snapshot). So if the
+;; bookmark file that is loaded is different from the one that was
+;; recorded for the display state, the recorded state is ignored.
+;;
+;;
+;;(@* "Automatic Saving")
+;; *** Automatic Saving ***
+;;
+;; Before getting into the topic of automatic saving, let me say this
+;; clearly once: BACK UP YOUR BOOKMARK FILE(S)!
+;;
+;; (Bookmark+ creates backups when your bookmark file is saved.
+;; Until bug #12507 is fixed, vanilla Emacs does not.)
+;;
+;; I recommend that you set option `bookmark-version-control' to `t',
+;; so that you get numbered backups.
+;;
+;; If you do use numbered backups then you might also want to
+;; customize option `delete-old-versions', setting the value to `t',
+;; so that you are not bothered by this prompt each time bookmarks
+;; are saved:
+;;
+;; Delete excess backup versions of <YOUR-INIT-FILE>? (y or n)
+;;
+;; See also nodes `Backup Names' and `Backup Deletion' in the Emacs
+;; manual.
+;;
+;; User option `bookmark-save-flag' controls whether and how often to
+;; automatically save the bookmark list to the bookmark file, thus
+;; syncing the two. You can toggle this option using `M-~' in the
+;; bookmark-list display.
+;;
+;; In the bookmark-list display, you can tell whether individual
+;; bookmarks have been modified since the last save: they are marked
+;; with `*'. I believe that this indication is robust and accurate
+;; (if not, please report a bug), but a word of caution: do not
+;; depend on it. The only way to be sure that your bookmarks have
+;; been saved is to save them. ;-)
+;;
+;; Is there a way to unmodify a single bookmark that you have
+;; changed? No, not unless it is the only one you modified. If you
+;; revert to the bookmarks as last saved, then all changes to all
+;; bookmarks (including addition and removal of bookmarks) are lost.
+;; If you want to work carefully when making multiple changes, then
+;; save any modifications you are sure of before you move on to
+;; others. If only one bookmark is modified then reverting to the
+;; bookmark file effectively unmodifies that bookmark.
+;;
+;; When you consult the doc for option `bookmark-save-flag' you see
+;; that besides values of `nil' and `t', meaning off and on, it can
+;; have a value that is the number of bookmark modifications to allow
+;; before automatically saving. If the value is 10, for instance,
+;; then the 11th modification triggers automatic saving.
+;;
+;; But a modification means any change to any bookmark. Typically,
+;; you are more interested in considering all of the changes caused
+;; by a given command as one modification. Why? Suppose you use a
+;; command such as `T > +' (`bmkp-bmenu-add-tags-to-marked'), which
+;; adds a set of tags to each of the marked bookmarks. Even if there
+;; have been no other modifications since you last saved bookmarks,
+;; if there are more marked bookmarks than your setting of
+;; `bookmark-save-flag' then automatic saving will kick in in the
+;; middle of the command. Some of the bookmarks with the added tags
+;; will be automatically saved. And that does not give you an
+;; opportunity to cancel the changes (e.g., by quitting without
+;; saving).
+;;
+;; This is the reason for option `bmkp-count-multi-mods-as-one-flag',
+;; whose default value is `t', which means count all of a sequence of
+;; modifications together as one modification, as far as
+;; `bookmark-save-flag' is concerned.
+
+;;(@* "Different Types of Jump Commands")
+;; ** Different Types of Jump Commands **
+;;
+;; When you jump to a bookmark, you can use completion to specify the
+;; bookmark name. `bookmark-jump' and `bookmark-jump-other-window',
+;; bound to `C-x j j' and `C-x 4 j j', are general commands. Their
+;; completion candidates include all of your bookmarks. With
+;; Bookmark+ you can easily have a large number of bookmarks.
+;;
+;; To provide more specificity, Bookmark+ provides many different
+;; bookmark jump commands. If you want to jump to a bookmark of a
+;; specific type, such as Info, you can use a Bookmark+ command that
+;; is specific to bookmarks of that type: only those bookmarks are
+;; completion candidates.
+;;
+;; There are thus type-specific commands: `bmkp-dired-jump',
+;; `bmkp-info-jump', and so on, bound to `C-x j d', `C-x j i', and so
+;; on. There are also commands to jump to bookmarks for the current
+;; buffer or for particular buffers or files
+;; (see (@> "Bookmarks for Specific Files or Buffers")).
+;;
+;; All bookmark jump commands are bound to keys that have the prefix
+;; `C-x j'. There is an other-window version of most jump commands,
+;; and it is bound to the same key as the same-window command, except
+;; the prefix is `C-x 4 j', not `C-x j'. For instance,
+;; `bmkp-dired-jump-other-window' is bound to `C-x 4 j d'.
+;;
+;; (In the bookmark-list display, you can use just `j' instead of
+;; `C-x 4 j', and just `J' (uppercase) instead of `C-x j'.)
+;;
+;; More precisely, the bookmark jump commands are on the prefix maps
+;; `bmkp-jump-map' and `bmkp-jump-other-window-map', which have the
+;; default bindings `C-x j' and `C-x 4 j'. You can bind these maps
+;; to any keys you like, by customizing options
+;; `bmkp-jump-map-prefix-keys' and
+;; `bmkp-jump-other-window-map-prefix-keys'.
+;;
+;; If you do not remember the different type-specfic bindings, you
+;; can use commands `bmkp-jump-to-type' and
+;; `bmkp-jump-to-type-other-window' (`C-x j :' and `C-x 4 j :').
+;; They work for any type, prompting you first for the type, then for
+;; a bookmark of that type (only).
+;;
+;; There are several commands for jumping to a bookmark with tags.
+;; The completion candidates can be those bookmarks that have all
+;; tags in a given set, some tags in a given set, all tags matching a
+;; regexp, or some tags matching a regexp. You are prompted for the
+;; set of tags or the regexp to match.
+;;
+;; These commands all have the prefix key `C-x j t'. The suffix key
+;; is `*' for "all" and `+' for "some". The regexp-matching commands
+;; precede the suffix key with `%'. For example, `C-x j t % +' jumps
+;; to a bookmark you choose that has one or more tags that match the
+;; regexp you input.
+;;
+;; There are some type-specific jump commands for bookmarks with
+;; tags. The key sequences for these include a key that indicates
+;; the bookmark type, after the `t' indicating tags. For example,
+;; commands for jumping to a file or directory bookmark having
+;; certain tags use the prefix `C-x j t f' (`f' for file). Similar
+;; commands for autofile bookmarks have prefix `C-x j t a' (`a' for
+;; autofile).
+;;
+;; For example, `C-x j t f % *' jumps to a file or directory bookmark
+;; you choose, where all of its tags match a regexp, and `C-x j t a
+;; +' finds a file tagged with at least one of the tags you input.
+;;
+;; In addition to the ordinary autofile "jump" commands, there are
+;; `find-file' versions: they read a file name using
+;; `read-file-name', instead of completing a bookmark name. - see
+;; (@> "Autofile Bookmarks"). These commands are available starting
+;; with Emacs 22.
+;;
+;; Bookmark names are global. File names are not; that is, the
+;; nondirectory portion is not. Suppose you have two similar
+;; directories with some like-named files, perhaps tagged in similar
+;; ways. Imagine image files of your vacations organized in
+;; different directories by year. It is sometimes useful to narrow
+;; your focus to the file bookmarks in one directory.
+;;
+;; Commands such as `bmkp-file-this-dir-jump' (`C-x j . f') offer as
+;; completion candidates only bookmarks for files and subdirs in the
+;; current directory (`default-directory'). For tags, there are
+;; equivalent commands. For example, `C-x j t . % *' is the same as
+;; `C-x j t f % *', but the destinations are limited to files in the
+;; current directory. All of the "this-dir" file jump commands are
+;; bound to the same keys as the general file jump commands, but with
+;; `.' instead of `f'.
+;;
+;; Remember that Bookmark+ collects lots of commands on only a few
+;; predefined prefix keys, primarily as a mnemonic device. Nothing
+;; requires you to use the long key sequence `C-x j t f % *' to visit
+;; a file that has a given set of tags. It is expected that you will
+;; bind short key sequences to commands that you use often.
+;;
+;; The `C-x j' and `C-x 4 j' bindings are global. In addition, in
+;; some modes `j' is bound to the corresponding type-specific jump
+;; command. For example, in Info mode, `j' is bound to
+;; `bmkp-info-jump'. (Dired is an exception here: `J' is used
+;; instead of `j', since `j' is already taken for `dired-goto-file'.)
+;; These commands are also added to the mode's menu-bar menu.
+;;
+;; In Dired mode, `C-j' is bound to a special Dired-specific jump
+;; command, `bmkp-dired-this-dir-jump', whose destinations all use
+;; the current directory (`default-directory'). The aim of `C-j' is
+;; not to change directories but to change to a different set of
+;; Dired markings, switches, inserted subdirectories, or hidden
+;; subdirectories for the same Dired directory.
+;;
+;; In addition to the predefined bookmark types, which you can use as
+;; described above, you can define a "type"-specific jump command for
+;; any set of bookmarks. That is, you can use any specific set of
+;; bookmarks as the completion candidates for a new jump command.
+;; Such a set is really only a pseudo-type: the actual bookmarks can
+;; each be of any type.
+;;
+;; You could use this feature, for example, to define a jump command
+;; for the bookmarks that belong to a given project.
+;;
+;; One way to define such a command is to first mark the bookmarks
+;; that you want to be the completion candidates, then use `C-c C-j'
+;; (command `bmkp-bmenu-define-jump-marked-command') in the bookmark
+;; list.
+;;
+;; The `*Bookmark List*' display defines a set of bookmarks, even
+;; without markings. So does each bookmark of type bookmark list,
+;; that is, a bookmark corresponding to a particular `*Bookmark
+;; List*' display state - see
+;; (@> "State-Restoring Commands and Bookmarks").
+;;
+;; You can capture the set of bookmarks corresponding to a `*Bookmark
+;; List*' display for use in navigation, that is, as the current
+;; "navigation list". Navigation here includes jumping and cycling
+;; - see (@> "Cycling, Navigation List").
+;;
+;; To capture in the navigation list the bookmarks corresponding to
+;; either the current `*Bookmark List*' display or a bookmark-list
+;; bookmark, use `C-x x B', which is bound to command
+;; `bmkp-choose-navlist-from-bookmark-list'. To then jump to a
+;; bookmark from such a navigation list, use `C-x j N' or `C-x 4 j N'
+;; (`bmkp-jump-in-navlist' or `bmkp-jump-in-navlist-other-window').
+
+;;(@* "Bookmark Annotations")
+;; ** Bookmark Annotations **
+;;
+;; With Bookmark+ you can bookmark many kinds of Emacs object.
+;; Bookmarks record locations - that is their primary purpose. They
+;; can also record annotations: general free-text descriptions of
+;; your choosing. An annotation is thus metadata that is associated
+;; with a bookmark. You can use it for any purpose you like.
+;;
+;; Command `bookmark-show-annotation' shows an annotation in
+;; read-only mode. You can use `C-x C-q' in the annotation buffer to
+;; switch to edit mode (and back again).
+;;
+;; You can use command `bookmark-edit-annotation' or `bmkp-annotate'
+;; anywhere to edit the annotation for a bookmark. For
+;; `bookmark-edit-annotation', you can choose among the bookmarks
+;; that already have annotations. With a prefix arg, you can choose
+;; any bookmark (and so create an annotation). Using `bmkp-annotate'
+;; is the same as using `bookmark-edit-annotation' with a prefix arg.
+;;
+;; In the annotation edit buffer, make your changes and then use `C-c
+;; C-c' to save the result. Use `C-x C-k' if you do not want to save
+;; the changes. You can also use `C-x C-q' and then `y' to confirm
+;; reverting the changes.
+;;
+;; Non-`nil' user option `bookmark-automatically-show-annotations'
+;; means that a bookmark's annotation is popped up whenever you jump
+;; to the bookmark. If the non-`nil' value is `edit' then the
+;; annotation buffer is in edit mode; if it is any other non-`nil'
+;; value then the buffer is in show (read-only) mode.
+;;
+;; In the `*Bookmark List*' display, bookmarks with annotations are
+;; marked by an `a' to the left of the bookmark name. You can use `a
+;; a' to show the annotation for the bookmark on the current line.
+;; You can use `a e' to create an annotation or edit an existing
+;; annotation for it. You can use `a >' to edit annotations for all
+;; of the marked bookmarks. You can use `a A' to show a list of the
+;; names and annotations of all annotated bookmarks.
+;;
+;; A bookmark annotation is stored as part of the bookmark itself.
+;; For this reason, you typically want to keep the text fairly short.
+;; In Bookmark+, the mode for viewing and editing a bookmark
+;; annotation is Org mode, by default. (To change the mode used,
+;; customize option `bmkp-annotation-modes-inherit-from'.)
+;;
+;; You can obtain the effect of using longer annotations, and some
+;; other advantages as well, by using "external annotations". These
+;; are annotations that are short and serve only as pointers to
+;; external files, URLs, or other bookmarks.
+;;
+;; Whenever you show the annotation of a bookmark (via `a' in the
+;; `*Bookmark List*' display, `bookmark-show-annotation', or
+;; `bookmark-automatically-show-annotations') and the annotation is
+;; such a pointer, the effect is to visit the destination.
+;;
+;; So for example, you can use bookmarks to one or more Org files to
+;; annotate (provide metadata for) one or more other bookmarks.
+;;
+;; You create an external annotation for a bookmark by using one of
+;; these forms as the annotation text.
+;;
+;; bmkp-annot-url: "FILE"
+;; bmkp-annot-url: "URL"
+;; bmkp-annot-url: "BOOKMARK"
+;;
+;; * FILE is an absolute file name. It is handled by
+;; `find-file-other-window'.
+;; * URL is a URL. It is handled by `browse-url'.
+;; * BOOKMARK is the name of a bookmark in the current bookmark
+;; alist.
+;;
+;; The double-quote characters are necessary here, so that you can
+;; include characters such as `SPC' in the name. The text must be on
+;; the first line of the annotation (not counting the commented
+;; instruction lines). It can be preceded only by whitespace.
+;;
+;; You can include other text in the annotation, after the
+;; destination specification, and you can see or edit it when you
+;; edit the annotation (e.g., using `C-u a' in buffer `*Bookmark
+;; List*'), but it is ignored when the annotation is "shown" (e.g.,
+;; using `a').
+;;
+;; In the `*Bookmark List*' display, `M-down' and `M-up' move the
+;; cursor down and up a line, respectively, but they also show the
+;; annotation, if any, of the bookmark at the new cursor location.
+
+;;(@* "Bookmark Tags")
+;; ** Bookmark Tags **
+;;
+;; In addition to annotating bookmarks with arbitrary metadata,
+;; Bookmark+ bookmarks can also be tagged, as a way to organize them,
+;; which also means as a way to organize the objects that are
+;; bookmarked.
+;;
+;; By "tagging" and "tag" in this context is meant associating
+;; keywords or other text with an object, typically in order to
+;; classify or characterize it. Tags are metadata about an object.
+;; This notion of tagging is sometimes called "delicious" tagging
+;; after the Web site www.delicious.com that popularized it
+;; (`https://en.wikipedia.org/wiki/Delicious_(website)').
+;;
+;; Be aware that there is another notion of "tag" associated with
+;; Emacs: that involving Emacs tags files, which record the locations
+;; of function, variable, etc. definitions in source files. There is
+;; no relation between the two notions of "tag".
+;;
+;; A bookmark tag is a string (or a cons whose car is a string - see
+;; (@> "Bookmark Tags Can Have Values")). You can add as many tags
+;; as you like to any bookmark, and multiple bookmarks can have the
+;; same tag(s). In fact, that's the whole idea behind using them for
+;; organizing.
+;;
+;; This feature is unrelated to the fact that bookmarks record
+;; locations and are useful for navigating. You can, if you want,
+;; use bookmarks to tag files in various ways purely for purposes of
+;; organizing them (e.g. into projects), whether or not you ever use
+;; the bookmarks as a way to visit them.
+;;
+;; For example, if you use `Dired+' (library `dired+.el'), then you
+;; can use `M-b' (`diredp-do-bookmark') in Dired to create an
+;; autofile bookmark for each of the marked files and subdirectories
+;; in the Dired buffer. Even if you never use those bookmarks for
+;; navigating to their targets, you can use them with tags to
+;; organize the targets, and thus operate on subsets of the marked
+;; files and subdirectories.
+;;
+;; And if you use libraries `Dired+' and `highlight.el' then
+;; autofiles are highlighted specially in Dired, and the highlighting
+;; indicates whether the file is tagged.
+;;
+;; By default, you create bookmarks without tags and add tags to them
+;; later. If you prefer, you can customize option
+;; `bmkp-prompt-for-tags-flag' to non-`nil' so that you are prompted
+;; to add tags immediately whenever you set (create or update) a
+;; bookmark.
+;;
+;; There are also some commands, such as `bmkp-tag-a-file' (`C-x x t
+;; + a') and `bmkp-untag-a-file' (`C-x x t - a'), that always prompt
+;; for tags to add or remove. (In general, the key `a' is used in
+;; key sequences for autofile bookmarks.)
+;;
+;; When you are prompted to enter a tag, you type some text then hit
+;; `RET'. If you want to include a newline character in the tag
+;; itself, use `C-q C-j' (`C-j' is the newline character). You can
+;; use `C-q' this way to enter any character. If you do use complex
+;; strings as tags then you might prefer to simply edit a bookmark's
+;; tags in a separate buffer. You can do that using `C-x x t e' (or
+;; `T e' in the bookmark-list display).
+;;
+;; Whenever you are prompted for a tag you can use completion. The
+;; completion candidates available are the tag names defined by
+;; option `bmkp-tags-for-completion'. The default value of this
+;; option is `current', meaning use only the tags from the bookmarks
+;; in the current bookmark list as candidates. You can customize the
+;; option to include specific tags or the tags from bookmarks in
+;; specific bookmark files.
+;;
+;; You can use command `bmkp-list-all-tags' to list all of the tags
+;; defined by option `bmkp-tags-for-completion' or, with a numeric
+;; prefix argument, only the tags corresponding to the current
+;; bookmark file. You can list the tag names only or (using a
+;; non-negative prefix arg) show the full tag definitions, which
+;; include any associated tag values (see (@> "Bookmark Tags Can Have Values")
+;; for information about tag values).
+;;
+;; To make tags more useful, Bookmark+ provides *lots* of commands:
+;; commands for adding, removing, copying, pasting, and renaming
+;; tags; commands for jumping to bookmarks with particular sets of
+;; tags; and commands for marking or unmarking (in buffer `*Bookmark
+;; List*') bookmarks that are tagged in various ways.
+;;
+;; Most commands pertaining to tags are by default on prefix key `C-x
+;; p t' - use `C-x x t C-h' to see them. In buffer `*Bookmark
+;; List*', commands pertaining to tags are on prefix key `T' - use `T
+;; C-h' to see them. And remember that you can use `C-h >' to
+;; describe all of the marked bookmarks, in the current sort order.
+;; The bookmark descriptions include the tags.
+;;
+;; When combined with other Bookmark+ commands (e.g. search,
+;; query-replace) that apply to the marked bookmarks in the
+;; `*Bookmark List*' window, you can really do quite a lot using
+;; bookmark tags. Use your imagination!
+;;
+;; See Also:
+;;
+;; * (@> "Bookmark Records: What A Bookmark Looks Like")
+;; * (@> "Bookmarking the Marked Files in Dired")
+;; * (@> "Opening Bookmarks Using Windows File Associations")
+;; * (@> "Tag Commands and Keys")
+;;
+;;
+;;(@* "Bookmark Tags Can Have Values")
+;; *** Bookmark Tags Can Have Values ***
+;;
+;; Bookmark tags are simply names (strings) when you create them.
+;; Nearly all of the predefined operations that use tags use these
+;; names: sorting, marking, jumping, and so on. But you can in fact
+;; add an associated value to any tag. This means that a tag can act
+;; just like an object attribute or property: it can be a name/value
+;; pair.
+;;
+;; To add a value to a tag that has none, or to change the current
+;; value of a tag, you use command `bmkp-set-tag-value', which is
+;; bound to `T v' in the bookmark list and bound to `C-x x t v'
+;; globally. You are prompted for the bookmark, the tag, and the new
+;; value.
+;;
+;; A tag value can be a number, symbol, string, list, vector, and so
+;; on. It can be as complex as you like. It can be any Emacs-Lisp
+;; object that has read syntax, that is, that is readable by the Lisp
+;; reader. (Everything that is saved as part of a bookmark must be
+;; readable; otherwise, your bookmark file could not be read
+;; (loaded).)
+;;
+;; Because tag values can be pretty much anything, you are pretty
+;; much on your own when it comes to making use of them. Bookmark+
+;; does not provide predefined functions for using tag values. In
+;; general, tag values are something you will use with home-grown
+;; Lisp code for your own purposes.
+;;
+;; However, you can easily make some interactive use of tag values
+;; with little effort. You can, for example, define a predicate that
+;; tests whether a bookmark has a tag value that satisfies some
+;; property (e.g. is a number greater than 3.14159265358979), and
+;; then you can use command `bmkp-bmenu-mark-bookmarks-satisfying' to
+;; mark those bookmarks.
+;;
+;; Tags that have the prefix "bmkp-" are reserved - do not name your
+;; own tags using this prefix.
+;;
+;; Currently, "bmkp-jump" is the only predefined bookmark tag. You
+;; can give this tag a value that is a function - it is called
+;; whenever the tagged bookmark is visited. Any Lisp-readable
+;; function value is allowed: a symbol or a lambda expression.
+;;
+;; For example, to display `Hello!' when a bookmark is visited you
+;; can use this:
+;;
+;; T v bmkp-jump RET (lambda () (message "Hello!"))
+;;
+;; The function that is the value of a "bmkp-jump" tag is called just
+;; after the the standard hook `bookmark-after-jump-hook' is invoked.
+;; You can use this tag to invoke functions that are specific to
+;; individual bookmarks; bookmarks can thus have their own, extra
+;; jump functions.
+;;
+;;
+;;(@* "Hierarchical Structures of Bookmarks?")
+;; *** Hierarchical Structures of Bookmarks? ***
+;;
+;; You can use tags to organize sets of bookmarks in various ways.
+;; But what about a simple, hierarchical (tree-shaped) structure like
+;; the one that you use for bookmarks in a web browser? You can get
+;; a similar effect with Bookmark+ by just using a tag-naming
+;; convention such as this:
+;;
+;; vacation/
+;; vacation/2017/
+;; vacation/2017/winter/
+;; vacation/2017/winter/photos/
+;; vacation/2017/summer/
+;; vacation/2017/summer/photos/
+;; vacation/2018/
+;; ...
+;;
+;; You need not tag any bookmarks with any particular part of such a
+;; pseudo-hierarchy. For example, you might tag some bookmarks with
+;; vacation/2017/winter/ and some with vacation/2017/winter/photos/,
+;; without bothering to have any that are tagged with just vacation/
+;; or just vacation/2017/.
+;;
+;; You are not limited to a single tree. You can have a tag such as
+;; vacation/2017/winter/ and a tag such as work/projects/2017/alpha/,
+;; without any need for those to have a common ancestor.
+;;
+;; How can you use such a tagging scheme?
+;;
+;; When you jump to a bookmark using a command that asks for tags,
+;; such as `C-x j t +' (`bmkp-some-tags-jump'), you can use
+;; completion. So you can, for example, type `vac TAB' to show all
+;; of your vacation tags (in `*Completions*'), and drill down,
+;; completing more, to pick whichever particular vacation tag you're
+;; interested in. This is similar to traversing a web-browser
+;; tree-like bookmarks menu. But jump commands that use tags let you
+;; match any number of tags at the same time, not just one.
+;;
+;; Completion against the set of existing tags is also available when
+;; you add tags to a bookmark. And if option
+;; `bmkp-prompt-for-tags-flag' is non-`nil' then you are prompted to
+;; add tags whenever you create or update a bookmark. But unlike the
+;; case for web-browser bookmark creation, classifying a bookmark
+;; when you create it or update it is optional. You can always add
+;; tags later, or not at all.
+;;
+;; Such a purely conventional, pseudo-hierarchy might sound like a
+;; silly hack, but it is at least as quick to use as is adding a
+;; bookmark to your tree of browser bookmarks. And it is more
+;; useful, because the organization is more flexible and you can have
+;; multiple, independent hierarchies.
+;;
+;; The tagging scheme just described can help you keep track of
+;; things, even though it is very simple. There is nothing special
+;; about it. You might come up with other conventions for
+;; classifying tags, which you find more convenient or more powerful.
+;; And remember that tags can be more than just names. They give you
+;; the full power of Lisp values - do with them whatever you like.
+
+;;(@* "Function, Sequence, Variable-List,... Bookmarks")
+;; ** Function, Sequence, Variable-List,... Bookmarks **
+;;
+;; Bookmarks are typically thought of only as recorded locations.
+;; Invoking a bookmark, called "jumping" to it, traditionally means
+;; just visiting its location. Bookmark+ looks at bookmarks in a
+;; more general way than that. A bookmark is a shortcut of some kind
+;; - nothing more. It is typically persistent, but it need not be
+;; (see (@> "Temporary Bookmarks")).
+;;
+;; A given type of bookmark is defined by its handler function, which
+;; can do anything you like. We've already seen the examples of
+;; region bookmarks, which restore the active region, and Dired
+;; bookmarks, which restore Dired markings, switches, inserted
+;; subdirectories, and hidden (sub)directories.
+;;
+;; A "function bookmark" simply invokes some function - any function.
+;; You can, for instance, define a window or frame configuration and
+;; record the configuration as a bookmark. Then jump to the bookmark
+;; to switch contexts. (You can also bookmark a desktop and jump to
+;; that.)
+;;
+;; Function bookmarks might not seem too interesting, since there are
+;; other ways to invoke functions in Emacs. But the other features
+;; of Bookmark+ combine with this feature. You can, for instance,
+;; tag function bookmarks.
+;;
+;; And you can combine them, invoking the functions sequentially.
+;; This is a particular case of using a "sequence bookmark", which
+;; simply records a sequence of bookmarks. The bookmarks in a
+;; sequence can be of any kind, including other sequence bookmarks.
+;;
+;; Command `bmkp-make-function-bookmark' (`C-x x c F') creates a
+;; function bookmark - you give it a function symbol or a lambda
+;; expression.
+;;
+;; A function bookmark can invoke a keyboard macro instead of a
+;; function. With a prefix argument, `bmkp-make-function-bookmark'
+;; creates a function bookmark from the last keyboard macro. Jumping
+;; to the bookmark executes the keyboard macro. A bookmark is thus
+;; one way to make a keyboard macro persistent.
+;;
+;; If you provide a prefix argument to the bookmark jump command or
+;; key that invokes a function bookmark, it is passed along to the
+;; function. If the bookmark invokes a keyboard macro then the
+;; prefix argument determines how many times the macro is invoked.
+;;
+;; The most general way to create or update a sequence bookmark is
+;; using command `bmkp-set-sequence-bookmark' (`C-x x c s'). You are
+;; prompted for the sequence bookmark name and the names of the
+;; bookmarks that form its sequence and are thus invoked by it
+;; sequentially.
+;;
+;; If the sequence bookmark already exists then a prefix argument
+;; determines whether the bookmarks you name are added to the
+;; existing sequence or replace it, and if added, whether before or
+;; after the bookmarks already in the sequence.
+;;
+;; Command `bmkp-wrap-bookmark-with-last-kbd-macro' (`C-x x c C-k')
+;; returns a sequence bookmark that invokes a bookmark you name and
+;; then invokes the last keyboard macro. You are prompted for the
+;; names of both bookmarks. If the sequence bookmark does not yet
+;; exist then it is created. (The bookmark to be added to the
+;; sequence need not exist yet, and it is not created by adding its
+;; name to the sequence.)
+;;
+;; If you enter the same name for the sequence bookmark and the
+;; bookmark to wrap with the keyboard macro, then the macro is simply
+;; added to that (sequence) bookmark.
+;;
+;; For example, if you enter `my-seq' for both of the
+;; `bmkp-wrap-bookmark-with-last-kbd-macro' prompts, then the last
+;; keyboard macro is added to sequence bookmark `my-seq'. Bookmark
+;; `my-seq' need not exist yet, in which case it is created, with the
+;; keyboard macro as its only member bookmark.
+;;
+;; If the bookmark to add to the sequence is itself a different
+;; (existing) sequence bookmark, then its member bookmarks are added
+;; to the sequence being updated (or created), either before or after
+;; its existing members, according to the prefix arg (which is passed
+;; to `bmkp-set-sequence-bookmark').
+;;
+;; Command `bmkp-bmenu-make-sequence-from-marked' creates a sequence
+;; bookmark from the marked bookmarks in the bookmark-list display,
+;; in their current order.
+;;
+;; If you use library `Dired+' (`dired+.el') then you can use command
+;; `diredp-do-bookmark-dirs-recursive' to create a Dired bookmark for
+;; the current Dired buffer and each of its marked subdirectories.
+;; Each of those subdirectories is handled similarly, and so on,
+;; recursively. This command also creates a sequence bookmark that
+;; includes all of these Dired bookmarks, so that it represents a
+;; tree (hierarchy) of Dired buffers that are opened together. This
+;; provides an alternative to inserting all of the relevant
+;; subdirectories into the same Dired buffer. With a prefix arg, all
+;; of the descendent Dired buffers are included, whether or not they
+;; are marked.
+;;
+;; You can also create a function bookmark directly from a keyboard
+;; macro, using command `bmkp-set-kmacro-bookmark'. And you can save
+;; the current set of keyboard macros as a bookmark, using command
+;; `bmkp-set-kmacro-list-bookmark' - jumping to it restores all of
+;; the macros'.
+;;
+;; A variable-list bookmark saves and restores the values of a set of
+;; variables. Command `bmkp-set-variable-list-bookmark' prompts you
+;; for the variables to include in the list and then sets the
+;; bookmark. Command `bmkp-jump-variable-list' (`C-x j v') restores
+;; the recorded variable values for the bookmark's buffer. You can
+;; also create variable-list bookmarks non-interactively, using
+;; function `bmkp-create-variable-list-bookmark'.
+;;
+;; If you use library `zones.el', then you can move among multiple
+;; restrictions (narrowings) in a buffer. The restrictions are
+;; stored in buffer-local variable `zz-izones'. Command
+;; `bmkp-set-izones-bookmark' bookmarks this value for the current
+;; buffer. Jumping to such a bookmark restores the saved ring/stack
+;; of restrictions.
+;;
+;;
+;;(@* "Little Persistent Named Nothings")
+;; *** Little Persistent Named Nothings ***
+;;
+;; OK, so a bookmark need not "go" anywhere. Function, sequence,
+;; variable-list, and some other kinds of bookmarks have no real
+;; "location" to move to or restore. But the bookmarks talked about
+;; so far at least have an associated action: you can "jump" to them,
+;; even if "jump" can mean a arbitrary action that might have nothing
+;; to do with reaching a destination.
+;;
+;; You can also have a *non-invokable* bookmark, that is, one that
+;; you cannot jump to. This is a bookmark whose handler is the
+;; function `ignore', which does nothing.
+;;
+;; What's the point of that? To record something persistently,
+;; without needing to manage the file(s) you record it in, and to be
+;; able to access that something by name.
+;;
+;; As an example, library Isearch+ provides one such use case. It
+;; lets you interactively add, modify, and remove Isearch filter
+;; predicates on the fly, providing more power and flexibility in
+;; searching.
+;;
+;; (A filter predicate is a function that accepts the current
+;; search-hit limits as arguments. If it returns `nil' then that
+;; search hit is excluded from searching; otherwise it is included.)
+;;
+;; You can also, on the fly, encapsulate the current suite of filter
+;; predicates as a new filter predicate. That is, you can manipulate
+;; a complex sequence of filters as a single predicate, using a
+;; simple name. And you can save the definition of that new
+;; predicate in a file, so you can use it again in future Emacs
+;; sessions.
+;;
+;; Alternatively, you can just bookmark the search predicate. The
+;; data saved in the bookmark is the suite of filters that is the
+;; advised value of `isearch-filter-predicate' at the time of
+;; bookmarking.
+;;
+;; Then, in a future Emacs session, while Isearching you can hit a
+;; key and enter the bookmark name (with completion), to apply that
+;; suite of filters again.
+;;
+;; Bookmarking is easier than defining a new predicate and bothering
+;; with a file to save it in. This is the kind of thing that
+;; bookmarks are for: persistently saving named bits of data for
+;; later retrieval by name.
+;;
+;; Because the saved data in this case (the filter definition) has no
+;; use outside the context of searching, there is no way to invoke it
+;; - no jump action. Its handler is `ignore'.
+;;
+;; You can apply all Bookmark+ features to non-invokable bookmarks:
+;; sort, edit, tag - whatever. Use Bookmark+ to organize them, even
+;; if you cannot invoke them.
+;;
+;; Non-invokable bookmarks are shown using face `bmkp-no-jump' in the
+;; bookmark-list display.
+;;
+;; It is also possible for a bookmark to have a handler other than
+;; `ignore', so that it is invokable, but that its jump action is
+;; appropriate only in certain contexts. This is the case, for
+;; instance, for an Icicles search-hits bookmark. You cannot invoke
+;; it outside the context of Icicles searching. For this reason,
+;; these bookmarks are also shown with face `bmkp-no-jump' in the
+;; bookmark-list display.
+
+;;(@* "Editing Bookmarks")
+;; ** Editing Bookmarks **
+;;
+;; In vanilla Emacs, you can edit the annotation associated with a
+;; bookmark. And you can rename a bookmark. But that is all. There
+;; is no easy way to really edit a bookmark.
+;;
+;; With Bookmark+:
+;;
+;; * You can use `r' in the bookmark-list display (or `C-x x r'
+;; elsewhere) to edit the name and the target file name (bookmarked
+;; location) of a bookmark. You are prompted for the new names.
+;;
+;; * You can use `e' in the bookmark-list display (or `C-x x E'
+;; elsewhere) to edit a complete bookmark - all of its information.
+;; You edit the internal Lisp sexp that represents the bookmark
+;; record. This is the same internal definition that you see when
+;; you use `C-u C-h RET' in the bookmark list.
+;;
+;; * You can use `E' in the bookmark-list display to edit the
+;; bookmark records of all of the marked bookmarks. Again, this
+;; means editing their internal Lisp sexps. In particular, this
+;; gives you an easy way to edit tags across multiple bookmarks.
+;; All of the editing power of Emacs is available.
+;;
+;; * You can use `T e' in the bookmark list (or `C-x x t e'
+;; elsewhere), to edit a bookmark's tags.
+;;
+;; For all but the first of these, you are placed in a separate
+;; editing buffer. Use `C-c C-c' when you are done editing, to save
+;; your changes. (To cancel, just kill the buffer: `C-x k'.)
+;;
+;; You can also clone (duplicate) a bookmark, using `M-n', and then
+;; edit any parts of it (e.g. using `e'). By default, the clone has
+;; the same name, but with "<2>" appended. With a prefix arg you are
+;; prompted for the name. Outside of the bookmark list you can use
+;; `C-x x 2' to clone a bookmark.
+;;
+;; There are many more keys and commands for editing bookmark tags.
+;; You can copy tags (`C-x x t c') from one bookmark and paste them
+;; to others, either replacing the original tags (`C-x x t C-y') or
+;; adding to them (`C-x x t q'). You can be prompted for some tags
+;; to add (`T +') or remove (`T -') from a bookmark. You can delete
+;; a tag from all bookmarks (`T d'). You can rename a tag everywhere
+;; (`T r'). And you can set a tag's value.
+;;
+;; As usual, all such commands are also available on the Bookmark+
+;; menus. The menus provide quick reminders of the available keys,
+;; as does the help from `?' in the bookmark-list display.
+;;
+;;
+;;(@* "Bookmark Records: What A Bookmark Looks Like")
+;; *** Bookmark Records: What A Bookmark Looks Like ***
+;;
+;; It's worth dispelling some of the mystery about what a bookmark is
+;; by mentioning what it looks like. This can help when you edit a
+;; bookmark record. The first thing to mention is that the basic
+;; structure of a bookmark record is described in the doc string of
+;; variable `bookmark-alist' - but I'll repeat some of that info
+;; here.
+;;
+;; A bookmark record is nothing more than a list whose first element
+;; is a string, the bookmark name. The other list elements are
+;; properties: key+value pairs that define the bookmark data. Each
+;; such pair is a cons: a nonempty list or a dotted list.
+;;
+;; The car of the property is its name (a Lisp symbol). The cdr is
+;; its value. What the value can be depends on the property - in
+;; general it can be any Lisp value (number, string, list, symbol,
+;; etc.). A property with a null cdr means the same thing as having
+;; no such property present. For example, having the empty property
+;; `(tags)' is the same as having no `tags' property at all.
+;;
+;; There is nothing more to it: properties can be anything you like,
+;; provided you provide some code to recognize them and do something
+;; with them.
+;;
+;; Of course, the types of properties you use most (maybe always) are
+;; predefined, and the vanilla `bookmark.el' code and the Bookmark+
+;; code recognize and use them. The most important and most typical
+;; property is this: `(filename . "/some/file/name.txt")', that is, a
+;; cons whose car is the symbol `filename' and whose cdr is the name
+;; (a string) of the bookmarked file.
+;;
+;; With that in mind, you can see that renaming a bookmark just means
+;; changing the string that is its car. And relocating a bookmark
+;; just means changing the string that is its `filename' - e.g., from
+;; `(filename . "/home/foo.el")' to `(filename . "/some/other.xml")'.
+;;
+;; If you already have a bookmark file, typically `~/.emacs.bmk',
+;; take a look at the bookmark records in it. A typical bookmark
+;; also has these properties, in addition to `filename': `position',
+;; `front-context-string', and `rear-context-string'. You can guess
+;; what they are - if not, see the doc string of `bookmark-alist'.
+;;
+;; A Bookmark+ bookmark typically has some additional properties that
+;; you can also guess. Properties `time' and `visits' are updated
+;; automatically each time you access the bookmark.
+;;
+;; Some bookmarks have a `handler' property whose value is a function
+;; that "jumps" to the bookmark "location". I put those two terms in
+;; quotes here because a handler is really just any function - it can
+;; do anything you like, and there need not be any associated
+;; location.
+;;
+;; Some Bookmark+ bookmarks, including autofile bookmarks, just
+;; "jump" to a file. The position in the file is unimportant, and
+;; "jumping" does not necessarily mean visiting the file with Emacs.
+;; In effect, such bookmarks are just wrappers around the file,
+;; letting you get the advantage of Bookmark+ features (tags etc.)
+;; for a file. Such bookmarks, which you can create using `C-x x c
+;; a' or `C-x x c f', contain a `file-handler' property instead of a
+;; `handler' property. The difference between the two is that the
+;; `file-handler' value is a function (Lisp function or shell
+;; command) to be applied to the file, not to the bookmark.
+;;
+;; Remember: A bookmark is just a persistent bit of information,
+;; typically meta-information about a file and a position in that
+;; file.
+;;
+;; I'm mentioning all of this to make the point that you cannot
+;; really hurt anything if you edit a bookmark record and you mess
+;; things up. The worst you can do is mess up all of your bookmarks
+;; by making the file unreadable as Lisp data. (It's always a good
+;; idea to back up your bookmark file from time to time.)
+;;
+;; And if each bookmark record after you edit it is a cons with a
+;; string car then your bookmarks are generally OK, even if you might
+;; have ruined the details of one or two of them. Suppose you
+;; somehow mistakenly delete the `a' in a `filename' property, for
+;; instance. No big deal - that bookmark no longer has a
+;; recognizable target location, but the other bookmarks are still
+;; OK.
+;;
+;; The most important property for Bookmark+ users (aside from
+;; `filename') is probably `tags'. Its value (the cdr) is a list of
+;; strings or conses - the bookmark's tags. When you create a tag,
+;; it is typically a string (just its name) - e.g. "blue". If you
+;; then give it a value as well, it becomes a cons with that string
+;; (the name) as car and the value as cdr - e.g. `("blue" . 42)' or
+;; `("blue" moonbeam 42)' - here the cdr is the list `(moonbeam 42)'.
+;; Here is an example of a `tags' property: `(tags "hegel" ("blue"
+;; . honeypot) "darwin")'. Most of the time you will use strings as
+;; tags. See also (@> "Bookmark Tags Can Have Values").
+;;
+;; When you edit bookmark records, just try to stay away from
+;; changing any properties that you are not familiar with. And make
+;; sure that when you're done you have a proper Lisp list (open
+;; parens closed etc.). If you've never played with Lisp before, do
+;; not panic.
+;;
+;; Be aware if you see dots (`.') that they are important, and they
+;; must be surrounded by whitespace: ` . '. The amount of whitespace
+;; never matters in Lisp (except inside a string etc.).
+;;
+;; Such a dot just separates the car of a cons from its cdr. (What's
+;; a cons? Just a car with a cdr!) If the cdr is a list then we
+;; typically drop the dot and the list's parens: We write `(b)'
+;; instead of `(b . ())' and `(a b)' instead of `(a . (b))' or `(a
+;; . (b . ()))'.
+;;
+;; Finally, remember that when you set an existing bookmark again,
+;; e.g., you use `C-x r m' and provide the name of an existing
+;; bookmark, the existing properties are generally lost. Some are
+;; automatically updated. Any that you might have added by editing
+;; are lost, and any that are provided by default by the bookmark
+;; handler are replaced. The only exceptions to this are the
+;; properties listed in option `bmkp-properties-to-keep', which by
+;; default means properties `tags' and `annotation'. Any existing
+;; tags and annotation are preserved when you update a bookmark.
+
+;;(@* "Bookmark-List Views - Saving and Restoring State")
+;; ** Bookmark-List Views - Saving and Restoring State **
+;;
+;; The bookmark list (buffer `*Bookmark List*') provides a view into
+;; the set of bookmarks. You can mark, sort, and hide (filter, omit)
+;; bookmarks - see (@> "The Bookmark List Display"). The state of
+;; the displayed bookmark list can thus change.
+;;
+;; At different times, and in different contexts, different views can
+;; be useful. Bookmark+ lets you save the current state of the
+;; displayed list and later restore it. There are a couple of
+;; different ways to do this.
+;;
+;;
+;;(@* "Quitting Saves the Bookmark-List State")
+;; *** Quitting Saves the Bookmark-List State ***
+;;
+;; If option `bmkp-bmenu-state-file' is non-`nil', which it is by
+;; default, then Bookmark+ remembers the last state of the bookmark
+;; list when you quit it or you quit Emacs, and it restores that
+;; state when you show the list again (which could be in the next
+;; Emacs session). You can think of this feature as your "Home" page
+;; for bookmarks, giving you a stepping stone to the files and
+;; directories you use most.
+;;
+;; If, for example, when you quit the bookmark list you are showing
+;; only bookmarks to Info nodes and UNIX manual pages, sorted in a
+;; particular way, and with some of them marked with `>' for
+;; particular processing, then the next time you open the list the
+;; same state is restored: the same set of bookmarks is shown, in the
+;; same order, with the same markings. Deletion flags (`D') and
+;; modification indicators (`*') are purposefully not saved as part
+;; of the display state - they are lost when you quit the display.
+;;
+;; You can turn off this automatic bookmark-list display state
+;; saving, if you want, by customizing option `bmkp-bmenu-state-file'
+;; to `nil'. And you can toggle this option at any time, using
+;; `C-M-~' in the bookmark list (command
+;; `bmkp-toggle-saving-menu-list-state'). In particular, if you want
+;; your next visit to the bookmark list to start out with a
+;; previously recorded state instead of the current state, just hit
+;; `C-M-~' before quitting the bookmark list.
+;;
+;;
+;;(@* "State-Restoring Commands and Bookmarks")
+;; *** State-Restoring Commands and Bookmarks ***
+;;
+;; In addition to automatically saving/restoring the final
+;; bookmark-list display state, you can save this state at any time,
+;; any number of times, for later restoration. This gives you the
+;; ability to create multiple persistent views of your bookmarks.
+;;
+;; There are two ways to do this:
+;;
+;; * Create a bookmark for the `*Bookmark List*' buffer itself: a
+;; bookmark-list bookmark.
+;;
+;; * Define a command that restores the bookmark-list state.
+;;
+;; When you use `C-x r m' (`bmkp-bookmark-set-confirm-overwrite') in
+;; buffer `*Bookmark List*' to create a bookmark-list bookmark, the
+;; current sort order, filter, regexp pattern, title, and omit list
+;; are saved as part of the bookmark. (These concepts are described
+;; below - see (@> "Bookmark List Display").) Jumping to such a
+;; bookmark restores all of these.
+;;
+;; Alternatively, you can define a command that does the same thing,
+;; but without creating another bookmark - use `C-c C-c'
+;; (`bmkp-bmenu-define-command') in the bookmark list to do this.
+;; You are prompted for the name of the new command. Use the command
+;; anytime (including in another Emacs session) to restore the
+;; bookmark list.
+;;
+;; Define any number of such commands for the views you use. The
+;; file for saving the definitions (see option
+;; `bmkp-bmenu-commands-file') is never overwritten, so you can also
+;; add other code to it manually, if you want. The file is read the
+;; first time the bookmark list is displayed in a given Emacs
+;; session.
+;;
+;; The state that is saved and restored using a bookmark-list
+;; bookmark or a command defined using `C-c C-c' is only a partial
+;; state. The current set of markings and some other information are
+;; not saved, in order to save disk space and save/restore time.
+;;
+;; Sometimes, however, you really want to save the entire
+;; bookmark-list state, creating a full snapshot. You can use `C-c
+;; C-C' (aka `C-c C-S-c', `bmkp-bmenu-define-full-snapshot-command')
+;; to do that. This defines a command that restores the bookmark
+;; list completely. That is the same thing that happens
+;; automatically (by default) whenever you quit the bookmark list (or
+;; Emacs), but defining snapshot commands lets you have multiple
+;; saved states and switch to them at will.
+;;
+;; Be aware, however, that full-snapshot command definitions can be
+;; quite large, since they each contain a copy of the current
+;; bookmark list and any accessory lists (hidden and marked bookmarks
+;; etc.).
+;;
+;; Whether you use `C-c C-c' or `C-c C-C' to define a state-restoring
+;; command or you create a bookmark-list bookmark, you can create a
+;; sequence bookmark that combines such bookmark-list restoration
+;; with activation of other bookmarks. (To include a state-restoring
+;; command in a sequence, you need to first create a function
+;; bookmark that uses the command, and then include that bookmark in
+;; the sequence.)
+
+;;(@* "Bookmarking without Visiting the Target")
+;; ** Bookmarking without Visiting the Target **
+;;
+;; There are several use cases for bookmarking a target without
+;; visiting it:
+;;
+;; 1. In an Emacs buffer you come across a reference or a link to a
+;; file or a URL. You bookmark the target without bothering to
+;; visit it first. You do not really care which position in the
+;; file is bookmarked.
+;;
+;; 2. In Dired, you mark certain files and then bookmark all (each)
+;; of them, in one operation.
+;;
+;; 3. In a compilation buffer (e.g. `*grep*', `*compile*') or an
+;; occur or multi-occur buffer (`*Occur*'), you bookmark one or
+;; more of the hits. Such a bookmark takes you to the appropriate
+;; position in the target file or buffer.
+;;
+;; 4. You bookmark a file that you might not even be able to visit in
+;; Emacs (in the sense of editing it in a buffer) - for example, a
+;; music file. "Jumping" to the bookmark performs an operation
+;; appropriate to the file - for example, playing music.
+;;
+;;
+;;(@* "Bookmarking a File or a URL")
+;; *** Bookmarking a File or a URL ***
+;;
+;; You can use commands `bmkp-file-target-set' and
+;; `bmkp-url-target-set', bound by default to `C-x x c f' and `C-x x
+;; c u', to bookmark any file or URL. Completion is available, the
+;; default file name or URL being determined by the text at point.
+;; In addition to the file or URL, you are prompted for the bookmark
+;; name. (In general, the keys `f' and `u' are used in key sequences
+;; for file and URL bookmarks, respectively.)
+;;
+;;
+;;(@* "Bookmarking the Marked Files in Dired")
+;; *** Bookmarking the Marked Files in Dired ***
+;;
+;; If you use `Dired+' (library `dired+.el'), then you can bookmark
+;; all of the marked files (and subdirectories) in a Dired buffer at
+;; once, as autofiles, even if you normally do not or cannot visit
+;; those files in Emacs. These keys are available in Dired:
+;;
+;; `M-b' - Bookmark each marked file
+;; `C-M-S-b' (aka `C-M-B') - Bookmark each marked file in a
+;; bookmark-file that you specify
+;; `C-M-b' - Bookmark each marked file in a
+;; bookmark-file you specify, and create
+;; a bookmark for that bookmark-file
+;;
+;; Each of these commands bookmarks each of the marked files and
+;; subdirectories as an autofile. By default, the bookmark file used
+;; for the latter two commands is in the current directory.
+;;
+;; If you use multiple `C-u' as a prefix arg for these commands, then
+;; you can bookmark all of the files in Dired, regardless of
+;; markings, as follows:
+;;
+;; `C-u C-u' - Use all files in Dired, except directories
+;; `C-u C-u C-u' - Use all files and dirs, except `.' and `..'
+;; `C-u C-u C-u C-u' - Use all files and all directories
+;;
+;; `C-M-b' not only bookmarks each of the marked files, it also
+;; creates a bookmark-file bookmark for that set of bookmarks. See
+;; (@> "Bookmark-File Bookmarks"), below.
+;;
+;; You can later "jump" to that bookmark to load its set of
+;; bookmarks. If you use `C-u' when you jump to it, then you switch
+;; bookmark files, so that `C-x x e' (or `C-x r l') displays only the
+;; bookmarks created from the marked files. Without `C-u', jumping
+;; to the bookmark-file bookmark simply loads its bookmarks into the
+;; current set of bookmarks.
+;;
+;;
+;;(@* "Bookmarking Compilation, Grep, and Occur Hits")
+;; *** Bookmarking Compilation, Grep, and Occur Hits ***
+;;
+;; In a similar way, you can bookmark the file or buffer positions of
+;; selected hits in a compilation buffer (including `*grep*') or an
+;; `occur' or `multi-occur' buffer.
+;;
+;; `C-c C-b' in such a buffer bookmarks the target of the hit at
+;; point. `C-c C-M-b' bookmarks the target of each hit in the
+;; buffer.
+;;
+;; `C-c C-M-b' in these buffers is thus similar to `M-b' in a Dired
+;; buffer. Unlike Dired, however, there is no way to mark such hits.
+;; Every hit is bookmarked.
+;;
+;; Nevertheless, you can get the same effect. Just use `C-x C-q' to
+;; make the buffer writable (e.g. temporarily), and then remove any
+;; hits that you do not want to bookmark. You can remove hits anyway
+;; you like, including by `C-k' and by regexp (`M-x flush-lines' or
+;; `M-x keep-lines').
+;;
+;; See also: (@> "Autonamed Bookmarks - Easy Come Easy Go"),
+;; bookmarking occur hits using autonamed bookmarks.
+;;
+;;
+;;(@* "Bookmarking Files That You Cannot Visit with Emacs")
+;; *** Bookmarking Files That You Cannot Visit with Emacs ***
+;;
+;; You use lots of files that you never visit using Emacs, but that
+;; you might like to keep track of or access in other ways: music
+;; files, image files, whatever.
+;;
+;; You can define a new kind of bookmark for any file type you are
+;; interested in, implementing a bookmark handler for it that
+;; performs the appropriate action on it when you "jump" to it. That
+;; action needs to be expressible using an Emacs function, but it
+;; need not have anything to do with visiting the file in Emacs.
+;;
+;; When you bookmark a target file that Emacs recognizes as an image
+;; or sound file, an appropriate handler is used automatically.
+;;
+;; After you create individual bookmarks for, say, music or image
+;; files, you can use `P B' in the bookmark-list display to show only
+;; those bookmarks, and then use `C-x r m' to bookmark that state of
+;; the bookmark-list.
+;;
+;; That bookmark-list bookmark in effect becomes a music playlist or
+;; an image library or slideshow. Jump to it anytime you want to
+;; listen to that set of music pieces or view those images. And you
+;; can use `C-x x B' and then `C-x x next' to cycle among the music
+;; pieces or images (slideshow). (See (@> "Cycling the Navigation List").)
+;;
+;; Together with the use of bookmark tags, this gives you a handy way
+;; to organize and access objects of any kind. See (@> "Bookmark Tags").
+;;
+;; You use option `bmkp-default-handlers-for-file-types' to control
+;; which operation (handler) to use for which file type. This is a
+;; set of associations (an alist) with each key being a regexp
+;; matching a file name, and with each associated value being a Lisp
+;; sexp that evaluates to either a shell command (a string) or an
+;; Emacs function (a symbol or lambda form).
+;;
+;; You can think of `bmkp-default-handlers-for-file-types' as
+;; somewhat analogous to `auto-mode-alist'. But it maps file-name
+;; patterns to file actions instead of mapping them to buffer modes.
+;; And it has an effect only when you use certain commands.
+;;
+;; The handler for the bookmark created invokes the shell command or
+;; the Emacs function with the file name as argument.
+;;
+;; Here is an example option value:
+;;
+;; (("\\.ps$" . "gsview32.exe")
+;; ("\\.html?$" . browse-url)
+;; ("\\.doc$" . w32-browser))
+;;
+;; This value causes creation of bookmarks that, when you jump to
+;; them, invoke:
+;;
+;; * shell command `gsview32.exe' on the bookmark's
+;; target file if it is PostScript (extension `.ps')
+;;
+;; * Emacs Lisp function `browse-url' on the file if it is HTML
+;; (extension `.htm' or `.html')
+;;
+;; * Emacs Lisp function `w32-browser' on the file if the file
+;; extension is `.doc' (e.g., a Microsoft Word file)
+;;
+;; The default value of `bmkp-default-handlers-for-file-types' is
+;; taken from the value of option `dired-guess-shell-alist-user'
+;; (from Dired X).
+;;
+;; The associations are checked in order, and the first one that
+;; matches the given file name is used. You can thus order them to
+;; deal with overlapping file-name patterns.
+;;
+;; If no matching file association is found in
+;; `bmkp-default-handlers-for-file-types', and if option
+;; `bmkp-guess-default-handler-for-file-flag' is non-`nil' (it is
+;; `nil' by default), then Bookmark+ will guess a shell command to
+;; use. It does this by matching the file name against
+;; `dired-guess-shell-alist-default' (also from Dired X). In Emacs
+;; 23 and later, if it finds no shell command that way then it
+;; guesses one based on mailcap entries.
+;;
+;; When a bookmark is created using `C-x x c f' or `C-x x c a' for a
+;; file that matches `bmkp-default-handlers-for-file-types', the
+;; shell command or Lisp function that "jumps to" (opens) the file is
+;; saved in the bookmark as property `file-handler' (not `handler').
+;;
+;;
+;;(@* "Opening Bookmarks Using Windows File Associations")
+;; *** Opening Bookmarks Using Windows File Associations ***
+;;
+;; If you use Microsoft Windows there is no need to define new
+;; bookmark types and handlers, if the action you want is the one
+;; that Windows associates with the file. You already have a set of
+;; file/program associations, and Bookmark+ recognizes these as
+;; alternative handlers.
+;;
+;; You can thus take advantage of Windows file associations to open
+;; bookmarks for files of all kinds. To do this, you also need
+;; library `w32-browser.el'. In the bookmark list, the following
+;; keys are bound to commands that open bookmarks using the
+;; associated Windows `Open' applications:
+;;
+;; `M-RET' - `bmkp-bmenu-w32-open'
+;; `M-mouse-2' - `bmkp-bmenu-w32-open-with-mouse'
+;; `M-o' - `bmkp-bmenu-w32-jump-to-marked'
+;;
+;; Windows file associations are always available to you, in addition
+;; to any other file associations that you define using
+;; `bmkp-default-handlers-for-file-types' (see
+;; (@> "Bookmarking Files That You Cannot Visit with Emacs")).
+;;
+;; You can thus have two different programs associated with the same
+;; kind of file. Your MS Windows file association for PostScript
+;; might, for example, use Adobe Distiller to create a PDF file from
+;; PostScript, while your `bmkp-default-handlers-for-file-types'
+;; association for PostScript might use GhostView to display it
+;; directly.
+;;
+;; Besides using `M-RET' etc. in buffer `*Bookmark List*', if in
+;; `bmkp-default-handlers-for-file-types' you register `w32-browser'
+;; as the association to use for a given file pattern, then you can
+;; use command `bmkp-w32-browser-jump' (not bound, by default)
+;; anywhere to open a bookmark whose file name matches that pattern,
+;; using its Windows file-association program.
+;;
+;; You can also specify `w32-browser' as the bookmark "type" when you
+;; use command `bmkp-jump-to-type' (`C-x j :'). Either of these
+;; approaches gives you a way to use completion to choose a bookmark
+;; to open using a Windows file association.
+;;
+;; Specifying such an association in
+;; `bmkp-default-handlers-for-file-types' means that bookmarks for
+;; such a file will have a `file-handler' value of `w32-browser', to
+;; "jump" to (i.e., open) the file.
+;;
+;; To set up a given file extension for use this way, add an entry
+;; (REGEXP . w32-browser) to option
+;; `bmkp-default-handlers-for-file-types', where REGEXP matches the
+;; file extension.
+;;
+;; For example, to make a command such as `bmkp-bookmark-a-file'
+;; (`C-x x c a') automatically bookmark `*.doc' files using the
+;; associated MS Windows program (typically MS Word), add this entry:
+;; ("\\.doc$" . w32-browser).
+;;
+;;
+;;(@* "Autofile Bookmarks")
+;; *** Autofile Bookmarks ***
+;;
+;; An autofile bookmark, or just an autofile, is a bookmark to a file
+;; or directory that uses the nondirectory part of its file name (or
+;; of its `directory-file-name', if a directory name) as the bookmark
+;; name.
+;;
+;; You can look at an autofile bookmark as just a wrapper around a
+;; file or directory: a way to attach meta information (such as tags)
+;; to it. But you can use an autofile bookmark much as you would use
+;; a file or directory.
+;;
+;; To create a new autofile bookmark, you can use
+;; `bmkp-bookmark-a-file' (aka `bmkp-autofile-set'), which is bound
+;; by default to `C-x x c a'. (In general, the key `a' is used in
+;; key sequences for autofile bookmarks.)
+;;
+;; If user option `bmkp-propertize-bookmark-names-flag' is non-`nil',
+;; which it is by default with Emacs 21 and later, then you can have
+;; multiple bookmarks with the same name. This is important for
+;; autofile bookmarks because the bookmark name is only the
+;; nondirectory part of the file name. This Bookmark+ feature lets
+;; you have different autofile bookmarks for files of the same name
+;; in different directories.
+;;
+;; In addition to the single autofile bookmark that you can create
+;; for a given absolute file location, you can of course create
+;; additional bookmarks to the same file or directory, using
+;; different bookmark names. Among other things, this lets you tag
+;; the same file or directory in different ways.
+;;
+;; You can use `C-x j a' (`bmkp-autofile-jump') or `C-x 4 j a'
+;; (`bmkp-autofile-jump-other-window') to visit an autofile bookmark.
+;; And there are commands for visiting an autofile that is tagged in
+;; certain ways. For example, `bmkp-autofile-some-tags-regexp-jump'
+;; (`C-x j t a % +') jumps to an autofile bookmark that has at least
+;; one tag matching a given regexp. See (@> "Tagging Files").
+;;
+;; You can create autofiles automatically whenever you use an Emacs
+;; file-cache command, by customizing user option
+;; `bmkp-autofile-filecache'. See the Emacs manual, node `File Name
+;; Cache'.
+;;
+;; This optional bookmark creation can replace adding the file to the
+;; cache, or it can be in addition to caching the file. This is done
+;; by advising command `file-cache-add-file', which means that it
+;; affects also the other Emacs file-cache commands that use that
+;; function, directly or indirectly:
+;;
+;; * `file-cache-add-directory'
+;; * `file-cache-add-directory-list'
+;; * `file-cache-add-directory-recursively'
+;; * `file-cache-add-directory-using-find'
+;; * `file-cache-add-directory-using-locate'
+;; * `file-cache-add-file-list'
+;;
+;; See the Emacs manual, node `File Name Cache'.
+;;
+;; If option `bmkp-autofile-access-invokes-bookmark-flag' is
+;; non-`nil' then regular access of a file or directory
+;; (e.g. `find-file') invokes the associated autofile bookmark, if
+;; there is one. This has the effect of updating the bookmark data,
+;; such as the number of visits. The default value of the option is
+;; `nil'. To set the option value, either use Customize
+;; interactively or use a Customize function.
+;;
+;; Finally, if you use libraries `Dired+' and `highlight.el' then
+;; autofiles are highlighted specially in Dired, and the highlighting
+;; indicates whether the file is tagged.
+;;
+;;
+;;(@* "A Type-Aware `find-file'")
+;; *** A Type-Aware `find-file' ***
+;;
+;; User option `bmkp-default-handlers-for-file-types' (see
+;; (@> "Bookmarking Files That You Cannot Visit with Emacs")) gives
+;; you a way to associate a file type, as determined by the file
+;; name (typically its extension) with a default file action. This
+;; is like MS Windows file associations, but it is specific to Emacs
+;; and Bookmark+. And it is useful for more than just bookmarks.
+;;
+;; Commands `bmkp-find-file' (`C-x j C-f') and
+;; `bmkp-find-file-other-window' (`C-x 4 j C-f') take advantage of
+;; this association to open files. If a file name matches no pattern
+;; in `bmkp-default-handlers-for-file-types' then these commands act
+;; like `find-file' and `find-file-other-window'. Otherwise, the
+;; invoke the associated file handler in
+;; `bmkp-default-handlers-for-file-types'.
+;;
+;; Invoking the handler is just what the ordinary autofile jump
+;; commands (e.g. `C-x j a') do. But `bmkp-find-file' is different
+;; in a couple of ways.
+;;
+;; Like vanilla `find-file' (`C-x C-f'), `C-x j C-f' and `C-x 4 j
+;; C-f' use `read-file-name' to prompt you for the file name. The
+;; completion candidates are the names of all of the files in the
+;; current directory (`default-directory'), that is, the directory of
+;; your current minibuffer input. This includes the names of any
+;; autofile bookmarks in the same directory. And like `C-x C-f' you
+;; can change directory, navigating up and down the file hierarchy.
+;; In sum, these commands are file-aware.
+;;
+;; The ordinary autofile jump commands on the other hand use
+;; `completing-read' to complete your input against all autofile
+;; bookmark names, regardless of directory. And since the bookmark
+;; names reflect only the relative file names, it is not so easy to
+;; distinguish two autofiles with the same name but in different
+;; directories. (`Icicles' can help here, BTW.)
+;;
+;; There is a `bmkp-find-file-' command that corresponds to each
+;; `bmkp-autofile-' command. For example,
+;; `bmkp-find-file-some-tags-regexp' (`C-x j t C-f % +') corresponds
+;; to `bmkp-autofile-some-tags-regexp-jump' (`C-x j t a % +'). All
+;; `bmkp-find-file' commands use `C-f' in their key bindings, as a
+;; reminder of their reading file names a la `find-file'.
+;;
+;; But whereas `C-x j C-f' and `C-x 4 j C-f' let you access any file,
+;; the other `bmkp-find-file-' commands, which find files that have
+;; certain tags, provide only autofiles as completion candidates.
+;; That's obvious, since files are tagged by bookmarking them.
+;;
+;; You can thus use the `C-f' commands to take advantage of
+;; file-action associations that you define. But if you want to
+;; associate metadata (e.g. tags) with files or directories, then you
+;; will want to create autofiles. You can do this when you invoke
+;; these commands, by providing a prefix argument. Thus, for
+;; example, `C-u C-x j C-f foo.doc' opens file `foo.doc', respecting
+;; any handler recorded for it via option
+;; `bmkp-default-handlers-for-file-types' - but it also creates an
+;; autofile bookmark for it.
+;;
+;; Whenever an autofile bookmark is used, regardless of whether you
+;; access it using a `bmkp-autofile*' command or a `bmkp-find-file*'
+;; command, the full bookmark record (including handler) is taken
+;; into account.
+;;
+;; Note, however, that the `C-f' tag commands differ from the `a' tag
+;; commands in how the completion candidates are filtered.
+;;
+;; For the former, `read-file-name' is passed a predicate that is
+;; applied to each file name in the directory, filtering out any such
+;; candidates that do not satisfy it (e.g., do not have the required
+;; tags).
+;;
+;; This happens before you type any input to match the file name.
+;; The predicate checks for a corresponding autofile and checks its
+;; tags (depending on the command). If there are lots of files in
+;; the current directory, this can take a while.
+;;
+;; For the latter, similar tests are made, but instead of testing
+;; each file in the current directory, these commands test each
+;; bookmark in the current bookmark list. If there are lots of
+;; bookmarks this can take a while.
+;;
+;; In some cases a `C-f' command is quicker; in some cases a `a'
+;; command is quicker.
+;;
+;; If you use `Icicles', then the performance hit for `C-f' when
+;; there are lots of files in a directory is greatly reduced. This
+;; is because `Icicles' applies the filtering predicate after, not
+;; before, you type text in the minibuffer. In other words, instead
+;; of testing each file in the directory, it tests only the files
+;; that match your input. (In addition, if you use `Icicles' then
+;; you get multi-command versions of each of these bookmark commands,
+;; which means that you can visit more than one file per command
+;; invocation.)
+
+;;(@* "Tagging Files")
+;; ** Tagging Files **
+;;
+;; Section (@> "Tags: Sets of Bookmarks") covers bookmark tags, which
+;; are persistent metadata that you define to help you organize
+;; bookmarks into meaningful sets.
+;;
+;; Section (@> "Autofile Bookmarks") describes autofile bookmarks,
+;; which, in effect, let you treat files and directories generally as
+;; if they were bookmarks. You can choose a file or directory to
+;; visit or act on by its name and location, but also by its bookmark
+;; metadata.
+;;
+;; In particular, you can tag a file or directory - that is, specify
+;; tags for its associated autofile bookmark. And you can then visit
+;; a file or directory that has a given set of tags. Bookmark+
+;; provides commands that automatically create and manipulate
+;; autofile bookmarks, that is, bookmarks that have the same name as
+;; the files or directories they tag.
+;;
+;; Command `bmkp-tag-a-file' (aka `bmkp-autofile-add-tags'), bound by
+;; default to `C-x x t + a', prompts you for a set of tags and a file
+;; or directory, and creates or sets the corresponding autofile
+;; bookmark. Command `bmkp-untag-a-file' (aka
+;; `bmkp-autofile-remove-tags'), bound by default to `C-x x t - a',
+;; similarly lets you remove specified tags from a file or directory.
+;;
+;; If you also use library `Icicles', then you can act on multiple
+;; files and directories during the same command (a "multi-command").
+;; You can thus all at once tag a set of files and directories the
+;; same way, or act on a set of files and directories that are tagged
+;; similarly. `Icicles' also lets you create autofiles or add or
+;; remove tags, on the fly, whenever you use commands (e.g. `C-x
+;; C-f') that access files or directories.
+;;
+;; If you also use library `Dired+' (`dired+.el') then you can use
+;; `C-+' to add tags to the marked files and directories, and `C--'
+;; to remove tags from them. You can use `C-M-+' and `C-M--' to do
+;; the same thing for the current file. You can also use items from
+;; the Dired menus to do these things.
+;;
+;; Bookmark+ provides two kinds of command for visiting files
+;; associated with bookmarks that have tags.
+;;
+;; The first kind uses bookmarks directly: you choose a bookmark
+;; name, not a file name, but the candidates are only file and
+;; directory bookmarks. These commands have the prefix `bmkp-file-'
+;; or `bmkp-autofile-'.
+;;
+;; As a special case, commands with the prefix `bmkp-file-this-dir-'
+;; limit the choices to bookmarks for files and subdirectories of the
+;; current directory. By default, the commands across all
+;; directories are on prefix key `C-x j t f', and those for the
+;; current directory only are on prefix key `C-x j t .'. See
+;; (@> "Different Types of Jump Commands") for more about these
+;; commands.
+;;
+;; The second kind of command is for visiting tagged files, that is,
+;; autofile bookmarks, just like the commands with prefix
+;; `bmkp-autofile-'. However, these commands do not handle the
+;; bookmark as such, but only its associated file or directory. They
+;; recognize its tags, but they pay no attention to any special
+;; handler or other recorded information.
+;;
+;; These commands have the prefix `bmkp-find-file-', and they are on
+;; the prefix key `C-x j t C-f'. The `C-f' here is intended to
+;; remind you of command `find-file' (`C-x C-f'). Like `find-file',
+;; they use `read-file-name' to read the bookmark's file name,
+;; instead of using `completing-read' to read the bookmark name.
+;;
+;; Yes, for an autofile bookmark the bookmark name and the relative
+;; file name are the same. But `read-file-name' is file-aware, and
+;; lets you browse up and down the directory hierarchy.
+;;
+;; The `bmkp-find-file-' commands are available only for Emacs 22 and
+;; later (because they use `read-file-name' with a PREDICATE
+;; argument).
+;;
+;; For example:
+;;
+;; `C-x j t f % +' is `bmkp-file-some-tags-regexp-jump'
+;; `C-x j t . % +' is `bmkp-file-this-dir-some-tags-regexp-jump'
+;; `C-x j t a % +' is `bmkp-autofile-some-tags-regexp-jump'
+;; `C-x j t C-f % +' is `bmkp-find-file-some-tags-regexp'
+;;
+;; * The first of these visits any file or directory bookmark that
+;; has at least one tag among the tags you specify, and you choose
+;; among bookmark names. The file or directory can be anywhere.
+;;
+;; * The second is similar to the first, but only bookmarks for files
+;; in the current directory are completion candidates.
+;;
+;; * The third is similar to the first, but only autofile bookmarks
+;; are completion candidates.
+;;
+;; * The fourth is similar to the third regarding tags, but it uses
+;; `read-file-name', so you can browse up and down the file
+;; hierarchy. The completion candidates are file and directory
+;; names, not bookmark names.
+;;
+;; If you use `Icicles', there are similar sets of commands, but they
+;; all let you act on multiple files and directories at the same time
+;; (multi-commands). For example, you can delete (or byte-compile
+;; or...) a set of files and directories according to their tags.
+;;
+;; Remember that you can create multiple bookmarks for the same file
+;; or directory, providing them with different sets of tags. (Only
+;; one of the bookmarks is the autofile bookmark.)
+;;
+;; You can also use multiple bookmark files (the files that record
+;; bookmarks). Different projects can thus have different tags for
+;; the same sets of files and directories, even using just autofile
+;; bookmarks. See (@> "Using Multiple Bookmark Files").
+;;
+;; A file or directory bookmark can have any number of tags, and
+;; multiple such bookmarks can have the same tag. You can sort,
+;; show/hide, or mark files and directories based on their tags.
+
+;;(@* "Using Multiple Bookmark Files")
+;; ** Using Multiple Bookmark Files **
+;;
+;; Bookmark-list views (see
+;; (@> "Bookmark-List Views - Saving and Restoring State")) provide
+;; one way to switch among various sets of bookmarks that you use.
+;; But that feature affects only the bookmarks that you see displayed
+;; in buffer `*Bookmark List*', not the actual set of available
+;; bookmarks.
+;;
+;; The bookmarks available to you are defined in a bookmark file. By
+;; default, they are stored in the file named by option
+;; `bmkp-last-as-first-bookmark-file', if non-`nil', otherwise in the
+;; file named by option `bookmark-default-file' (`~/.emacs.bmk', by
+;; default).
+;;
+;; If you use only one bookmark file then you never need to load or
+;; save it manually. Emacs does that for you automatically.
+;;
+;; But you can have multiple bookmark files if you want, and at any
+;; time you can change the bookmark file that is current. To do
+;; that, use `C-x x L' (or just `L' in the bookmark-list display),
+;; which is bound to command `bmkp-switch-bookmark-file-create'.
+;; Having multiple bookmark files gives you an added degree of
+;; flexibility.
+;;
+;; By default, the last bookmark file you used, in your last Emacs
+;; session, is the initial bookmark file that is loaded automatically
+;; in your next session. But if you prefer, you can make Bookmark+
+;; always start with the same bookmark file
+;; (`bookmark-default-file'). User option
+;; `bmkp-last-as-first-bookmark-file' controls this.
+;;
+;; You can easily see which bookmark file is current at any time: It
+;; is shown at the top of buffer `*Bookmark List*', and it is near
+;; the top of the help output from command
+;; `bmkp-bmenu-mode-status-help', which is what is bound to `?' and
+;; `C-h m' in buffer `*Bookmark List*'.
+;;
+;; When you switch to another bookmark file, the default choice for
+;; the file to switch to is the last bookmark file you used (in the
+;; same session). So it is trivial to toggle back and forth between
+;; two bookmark files: just hit `RET' to accept the default.
+;;
+;; When bookmarks are saved automatically, or when you save them
+;; using `bookmark-save' (`S' in the bookmark-list display or `C-x x
+;; s' globally) and you don't use a prefix argument, they are saved
+;; in the current bookmark file.
+;;
+;; You can turn off the automatic saving of the current bookmark
+;; file, by customizing option `bookmark-save-flag' to `nil'. And
+;; you can toggle this option at any time, using `M-~' in the
+;; bookmark list (command `bmkp-toggle-saving-bookmark-file').
+;;
+;; Besides using multiple bookmark files as *alternatives*, you can
+;; combine them, using them as component bookmark subsets (like
+;; modules). To do that, use command `C-x x l' (lowercase `l'),
+;; which is bound to `bookmark-load', and do not use a prefix
+;; argument. (Using a prefix argument with `C-x x l' is the same as
+;; using `C-x x L': it switches bookmark files.) Here too the
+;; default is the name of the last bookmark file that you used.
+;;
+;; In the `*Bookmark List*' display you can use `M-l' to load all of
+;; the bookmark files corresponding to the marked bookmark-file
+;; bookmarks, in the order in which they are displayed. Any non
+;; bookmark-file bookmarks that are marked are ignored. Before
+;; loading, if any of your currently loaded bookmarks have been
+;; modified then you are asked if you want to save them first, before
+;; loading the others.
+;;
+;; After loading, to avoid confusion and possible mistakes, automatic
+;; saving to the current bookmark file is turned off. You can always
+;; use `M-~' to turn it back on again. And remember that, as long as
+;; you have not saved bookmarks after loading, you can always use
+;; `C-u g' to revert to the bookmarks saved in the bookmark file.
+;;
+;; To create additional bookmark files, to use either as alternatives
+;; or as components, you can either copy an existing bookmark file or
+;; use `bmkp-empty-file' (`C-x x 0') to create a new, empty bookmark
+;; file. If you use `C-x x 0' with an existing bookmark file, then
+;; its bookmarks are all deleted - it is emptied.
+;;
+;; Instead of simply copying a bookmark file, you can use
+;; `bookmark-save' with a prefix argument, or use `bookmark-write'
+;; (bound to `C-x x w'), to save the currently defined bookmarks to a
+;; different bookmark file.
+;;
+;; However a bookmark file was created, you can switch to it and then
+;; add or delete bookmarks selectively, to change its content.
+;; Remember too that you can delete bookmarks from the current set
+;; using command `bookmark-delete' (`C-x x d') or, in the bookmark
+;; list, using `d' plus `x' or marking then `D'.
+;;
+;; Deleting bookmarks from a bookmark file is one way of editing it.
+;; Another is to copy or move bookmarks from one bookmark file to
+;; another. In the bookmark-list display, you can copy or move the
+;; marked bookmarks (or the current bookmark, if none are marked)
+;; from the current bookmark file to another that you name, using `Y
+;; > +' (`bmkp-bmenu-copy-marked-to-bookmark-file') and `Y > -'
+;; (`bmkp-bmenu-move-marked-to-bookmark-file'), respectively. And
+;; you can use `Y > 0'
+;; (`bmkp-bmenu-create-bookmark-file-from-marked') to create a new
+;; bookmark file by copying the marked bookmarks. With a prefix arg,
+;; `Y > 0' creates also a bookmark-file bookmark.
+;;
+;; In any location (any file or any buffer that can be bookmarked),
+;; you can switch to a bookmark file that has only bookmarks for the
+;; current file or buffer, creating such a file on the fly if none
+;; exists. To do this, use `C-x x C-l'
+;; (`bmkp-switch-to-bookmark-file-this-file/buffer').
+;;
+;; NOTE:
+;;
+;; Unlike the other ways of organizing bookmarks into sets (tags,
+;; bookmark-list bookmarks, etc.) bookmark files represent
+;; physical, not logical, groupings of bookmarks. A bookmark file
+;; contains complete bookmark records.
+;;
+;; If you copy a bookmark from one bookmark file to another, the
+;; copy is an independent bookmark: it has no relation to the
+;; bookmark it was copied from. Changes to the copy or the
+;; bookmark it was copied from do not affect each other.
+;;
+;; This means that to use bookmark files for organizing bookmarks
+;; you will typically move, not copy, bookmarks between them (or
+;; copy and later delete). Remember that you can load multiple
+;; bookmark files to access their bookmarks together in a session.
+;; Think of your bookmark files as independent modules that you can
+;; combine.
+;;
+;; See Also: (@> "Bookmark+ Load Order and Option `bookmark-default-file'").
+;;
+;;
+;;(@* "Bookmark-File Bookmarks")
+;; *** Bookmark-File Bookmarks ***
+;;
+;; A bookmark file is an excellent, persistent way to represent a set
+;; of bookmarks. In particular, it can represent a project or a
+;; project component. Switch among bookmark files to access
+;; different projects. Load project components as you need them.
+;;
+;; You can load a bookmark file using `C-x x L' (switch) or `C-x x l'
+;; (accumulate). As a convenience, you can also load a bookmark file
+;; by jumping to a bookmark-file bookmark.
+;;
+;; You use command `bmkp-set-bookmark-file-bookmark', bound to `C-x x
+;; y', to create a bookmark-file bookmark. Jumping to such a
+;; bookmark just loads the bookmark file that it records. With `C-u'
+;; (e.g. `C-u C-x j y project-foo'), jumping switches bookmark files.
+;; Without `C-u' it accumulates the loaded bookmarks.
+;;
+;; You can also use commands `bmkp-bookmark-file-load-jump' and
+;; `bmkp-bookmark-file-switch-jump' (unbound by default), which load
+;; and switch without prompting you for confirmation or whether to
+;; first save the current bookmark file.
+;;
+;; A bookmark-file bookmark is not only an added convenience. You
+;; can also use it in combination with other Bookmark+ features, such
+;; as tagging.
+;;
+;; As a shortcut, in Dired (if you use library `Dired+'), `C-M-b'
+;; creates a bookmark-file bookmark. The bookmark file that it
+;; records contains autofile bookmarks to each of the files and
+;; subdirectories that was marked in Dired at the time it was
+;; created. Jumping to that bookmark-file bookmark makes those
+;; (marked) files and subdirectories available as bookmarks. See
+;; also (@> "Use Dired to Bookmark Files without Visiting Them").
+;;
+;; Note that the bookmark file in which a bookmark-file bookmark is
+;; recorded is not the same as the bookmark file recorded in that
+;; bookmark.
+;;
+;; For example, when you use `C-M-b' in Dired, the bookmark-file for
+;; the marked files is, by default, file `.emacs.bmk' in the Dired
+;; directory. So if you are in directory `/foo/bar' the default
+;; bookmark file for the marked files is `/foo/bar/.emacs.bmk'. But
+;; the new bookmark-file bookmark created is recorded in the current
+;; bookmark file, whatever that might be (e.g. `~/.emacs.bmk').
+
+;;(@* "The Bookmark List Display")
+;; ** The Bookmark List Display **
+;;
+;; Bookmark+ enhances the bookmark list (aka the bookmark "menu
+;; list", a misnomer) that is displayed in buffer `*Bookmark List*'
+;; when you use `C-x x e' or `C-x r l' (command
+;; `bookmark-bmenu-list').
+;;
+;; At the top of the bookmark-list display is this header
+;; information:
+;;
+;; * The bookmark file used currently. This is important because
+;; Bookmark+ makes it easy for you to have multiple bookmark files
+;; and switch among them.
+;;
+;; * A title that describes the kinds of bookmarks listed, that is,
+;; it reflects athe current filtering, if any.
+;;
+;; For example, this header indicates that the current bookmark file
+;; is `c:/.emacs.bmk' and only file and directory bookmarks are
+;; shown:
+;;
+;; Bookmark file:
+;; c:/.emacs.bmk
+;;
+;; File and Directory Bookmarks
+;; ----------------------------
+;;
+;; (Bookmark+ does not use the sliding header line of vanilla Emacs
+;; 24+, which means that option `bookmark-bmenu-use-header-line' has
+;; no effect. You do not need to see `Bookmark' and `File' column
+;; headers as you scroll.)
+;;
+;; Bookmarks are highlighted to indicate their type. You can mark and
+;; unmark bookmarks, show or hide bookmarks of particular types, and
+;; more. Bookmarks that have tags are marked with a `t'. Bookmarks
+;; that have an annotation are marked with an `a' (not with a `*' as
+;; in vanilla `bookmark.el'). Bookmarks that have been modified
+;; since the last save of the bookmark file are marked with a `*'.
+;; Bookmarks that have bookmark-highlight override settings (see
+;; (@> "Defining How to Highlight")) are marked with a one-character
+;; pink background.
+;;
+;; Use `?' or `C-h m' in buffer `*Bookmark List*' for more
+;; information about the bookmark list, including the following:
+;;
+;; * The current status of sorting, filtering, and marking.
+;;
+;; * A legend for the faces used for different bookmark types.
+;;
+;;
+;;(@* "Jumping To Bookmarks from the Bookmark List Display")
+;; *** Jumping To Bookmarks from the Bookmark List Display ***
+;;
+;; Bookmark visiting (jumping) commands are globally on prefix keys
+;; `C-x j' and `C-x 4 j'. In the bookmark-list display they are
+;; additionally on `j' (other window) and `J' (same window). In
+;; addition, `j >' is bound to `bmkp-bmenu-jump-to-marked', which
+;; jumps to each of the marked bookmarks in other windows.
+;;
+;;
+;;(@* "Tag Commands and Keys")
+;; *** Tag Commands and Keys ***
+;;
+;; There are lots of tag-related bookmark commands, and most are
+;; bound to keys in buffer `*Bookmark List*' as well as to other keys
+;; outside it. How can you keep the commands straight or remember
+;; their keys?
+;;
+;; In the bookmark list display, tags-command keys begin with prefix
+;; key `T'. Elsewhere, they begin with prefix key `C-x x t' (or `C-x
+;; j t', for jump commands - see (@> "Different Types of Jump Commands")).
+;;
+;; `C-h m' (or `?') is your friend, of course. Likewise `T C-h',
+;; `C-x x t C-h', and `C-h >' (which describes the marked bookmarks).
+;; Beyond that, the tag-related keys that are more than two
+;; keystrokes are organized as follows:
+;;
+;; They all have the prefix key `T'.
+;;
+;; `m' means mark
+;; `u' means unmark
+;; `>' stands for the marked bookmarks
+;; `*' means AND (set intersection; all)
+;; `+' means OR (set union; some/any)
+;; `~' means NOT (set complement)
+;;
+;; The key `T m *', for instance, marks (`m') the bookmarks that are
+;; tagged with all (`*' = AND) of a given set of tags. It prompts you
+;; for one or more tags that the bookmarks must have, and it marks
+;; all bookmarks that have all of the tags you enter.
+;;
+;; The key `T u ~ +' unmarks (`u') the bookmarks that do not (`~')
+;; have any (`+' = OR) of the tags you specify. And so on.
+;;
+;; The marking and unmarking commands for tags compare the tags a
+;; bookmark has with tags that you enter. Any bookmarks that have no
+;; tags are ignored - they are neither marked nor unmarked by these
+;; commands.
+;;
+;; `+' and `-' can also mean add and remove tags, respectively, and
+;; `>' stands for the marked bookmarks. So `T > +' adds (`+') one or
+;; more tags to each of the marked (`>') bookmarks.
+;;
+;; In general, the tag-related commands let you enter a set of tags,
+;; one at a time. Thus, instead of having a command that adds a
+;; single tag to the current bookmark, you have a command that adds
+;; any number of tags to it. To add just a single tag, hit `RET'
+;; twice: once to enter the tag, and once again to indicate that it
+;; is the last (i.e., the only) one.
+;;
+;; If you just hit `RET' immediately, specifying an empty set of
+;; tags, then each of the commands does something appropriate. For
+;; `T m *', for instance, an empty list of tags means to mark (only)
+;; the bookmarks that have any tags at all.
+;;
+;; Finally, for the marking/unmarking tags commands, a prefix
+;; argument flips the sense of the command, in this way:
+;;
+;; "some are" -> "some are NOT", i.e., "not all are" (and vice versa)
+;; "all are" -> "all are NOT", i.e., "none are" (and vice versa)
+;;
+;; In other words:
+;;
+;; C-u T m * = T m ~ + (all are NOT = not some are)
+;; C-u T m ~ + = T m * (not some are NOT = all are)
+;; C-u T m + = T m ~ * (some are NOT = not all are)
+;; C-u T m ~ * = T m + (not all are NOT = some are)
+;;
+;; You'll figure it out ;-).
+;;
+;; Other important keys pertaining to tags (the keys in parentheses
+;; work in any buffer, not just buffer `*Bookmark List*'):
+;;
+;; * `C-h RET' (`C-h M') shows you the tags that belong to a
+;; bookmark. With a prefix argument it shows you the full internal
+;; form of the tags, that is, the name+value pairs.
+;;
+;; * `C-h >' describes all of the marked bookmarks, in the current
+;; sort order. The descriptions include the tags. (You can use `T
+;; m * RET' to mark all of the tagged bookmarks.)
+;;
+;; * `T e' (`C-x x t e') lets you edit a bookmark's tags.
+;;
+;; * `T l' (`C-x x t l') lists all tags currently known to Emacs
+;; (across all bookmarks).
+;;
+;; * `T +' (`C-x x t + b') adds some tags to a bookmark.
+;; `T -' (`C-x x t - b') removes some tags from a bookmark.
+;; `T 0' (`C-x x t 0) removes all tags from a bookmark.
+;; `T d' (`C-x x t d) removes a set of tags from all bookmarks.
+;;
+;; In the bookmark list display you can also sort bookmarks according
+;; to how they are tagged, even in complex ways. See
+;; (@> "Sorting Bookmarks").
+;;
+;;
+;;(@* "Tags: Sets of Bookmarks")
+;; *** Tags: Sets of Bookmarks ***
+;;
+;; The best way to think about tags is as names of sets. All
+;; bookmarks tagged `blue' constitute the bookmark set named `blue'.
+;;
+;; The bookmarks visible in the bookmark list at any time also
+;; constitute an unnamed set. Likewise, the marked bookmarks and the
+;; unmarked bookmarks are unnamed sets. Bookmark+ is all about
+;; helping you act on sets of Emacs objects. Bookmarks are named,
+;; persistent pointers to objects such as files and filesets.
+;; Bookmark tags are named, persistent sets of bookmarks (and hence
+;; of their target objects).
+;;
+;; The marking commands make it easy to combine sets as unions or
+;; intersections. And you can give the result a name for quick
+;; access later, just by adding a new tag. in other words, do the
+;; set-definition work only once, and name the result.
+;;
+;; How would you tag as `Java IDE Projects' the bookmarks that are
+;; already tagged both `Java' and `ide'?
+;;
+;; 1. `T m * Java RET ide RET RET', to mark them.
+;; 2. `T > + Java IDE Projects RET RET, to tag them.
+;;
+;; How would you sort your bookmarks, to show all those tagged both
+;; `blue' and `moon' first?
+;;
+;; 1. `T m * blue RET moon RET RET', to mark them.
+;; 2. `s >' to sort the marked bookmarks first
+;; (see (@> "Sorting Bookmarks"), below).
+;;
+;; If you wanted to show only the marked bookmarks, instead of
+;; sorting to put them first in the list, you would use `>'
+;; instead of `s >'.
+;;
+;; How would you query-replace the set of files that are tagged with
+;; any of the tags `alpha', `beta', and `gamma', but are not tagged
+;; `blue' or `moon'?
+;;
+;; 1. `F S', to show only the file bookmarks.
+;; 2. `T m + alpha RET beta RET gamma RET RET', to mark the
+;; bookmarks that have at least one of those tags.
+;; 3. `T u + blue RET moon RET RET', to unmark those that are
+;; tagged `blue' or `moon'.
+;; 4. `M-q' to query-replace the marked files.
+;;
+;; If that were a set of files that you used often, then you would
+;; name the set by giving the files a new tag.
+;;
+;; The point is that bookmarks, and bookmark tags in particular, let
+;; you define and manipulate sets of Emacs objects. It doesn't
+;; matter how you define such a set: regexp matching (marking,
+;; filtering), by object type, by tag combinations... Sets need not
+;; be named to act on them, but you can provide them with persistent
+;; names (tags) to avoid redefining them over and over. Manipulation
+;; of bookmarked objects includes visiting, searching, and
+;; query-replacing. And you can define your own bookmark types
+;; (using bookmark handlers) and associated manipulations.
+;;
+;;
+;;(@* "Open Dired for the Marked File Bookmarks")
+;; *** Open Dired for the Marked File Bookmarks ***
+;;
+;; You've seen that the bookmark list has many features that are
+;; similar to Dired features. But Dired is specialized for files and
+;; directories, and it has many more features for manipulating them.
+;; The bookmark list is not intended to replace Dired.
+;;
+;; You can, however, use the bookmark list to take advantage of
+;; arbitrary Dired features for file and directory bookmarks.
+;; Command `bmkp-bmenu-dired-marked' (`M-d >') weds Bookmark+'s
+;; set-defining and set-manipulating features (tagging, marking,
+;; filtering etc.) to Dired's file-manipulating features.
+;;
+;; `M-d >' opens a Dired buffer that is specialized for just the
+;; files and directories whose bookmarks are marked in the bookmark
+;; list. (Other marked bookmarks are ignored by the command.) The
+;; files and directories can be located anywhere; they need not be in
+;; the same directory. They are listed in Dired using absolute file
+;; names.
+;;
+;; (In Emacs versions prior to release 23.2, only local files and
+;; directories can be handled, due to Emacs bug #5478. In such
+;; versions, remote-file bookmarks are ignored by `M-d >'.)
+;;
+;; This Bookmark+ feature makes sets of files and directories
+;; immediately amenable to all of the operations provided by Dired.
+;;
+;; It is particularly useful in conjunction with tags. Use bookmark
+;; tags and marks to define a possibly complex set of file and
+;; directory bookmarks. Then hit `M-d >' to list them in a Dired
+;; buffer. Then use any Dired commands you want to act on any of
+;; them.
+;;
+;; For example, to compress bookmarked files that are tagged with
+;; both `blue' and `moon':
+;;
+;; 1. Mark them using `T m * blue RET moon RET RET'.
+;; 2. Open Dired for them using `M-d >'.
+;; 3. Mark them in Dired, then compress them using `Z'.
+;;
+;; Since tags are persistent, Bookmark+ gives you a good way to
+;; define an arbitrary set of files as a project and then open them
+;; in Dired at any time to operate on them.
+;;
+;; If you use `Dired+' (library `dired+.el'), then a similar feature
+;; is available for the marked files and directories: You can use
+;; `C-M-*' in Dired to open a separate Dired buffer for them only.
+;; You can of course then bookmark that resulting Dired buffer, if
+;; you like.
+;;
+;; If you use `Icicles', then whenever you use a command that reads a
+;; file (or directory) name, you can use `M-|' during file-name
+;; completion to open Dired on the currently matching set of file
+;; names. That is, this is the same kind of special Dired buffer
+;; that is provided for file and directory bookmarks by `M-d >' in
+;; the bookmark list.
+;;
+;;
+;;(@* "Marking and Unmarking Bookmarks")
+;; *** Marking and Unmarking Bookmarks ***
+;;
+;; Bookmark+ enhances the marking and unmarking of bookmarks in the
+;; bookmark list in several ways. These enhancements are similar to
+;; features offered by Dired and Dired-X. You can use:
+;;
+;; * `% m' to mark the bookmarks that match a regexp. The entire
+;; line in the bookmark list is checked for a match, that is, both
+;; the bookmark name and the file name, if shown.
+;;
+;; * `M-DEL' (or `U') to unmark all bookmarks, or all that are marked
+;; `>', or all that are flagged `D' for deletion.
+;;
+;; * `t' to toggle (swap) the marked and unmarked bookmarks: those
+;; that are marked become unmarked, and vice versa.
+;;
+;; * `>' to show only the marked bookmarks or `<' to show only the
+;; unmarked bookmarks. Repeat to show them all again.
+;;
+;; * `F M', `I M' etc. to mark only the file bookmarks, Info
+;; bookmarks etc. (The first key here is the same as the
+;; corresponding filter key, e.g. `F' for files - see next topic.)
+;;
+;; * `O M' to mark the orphaned bookmarks, that is, those whose
+;; recorded files have been renamed or deleted. You can then
+;; relocate or delete the bookmarks, as appropriate.
+;;
+;;
+;;(@* "Filtering Bookmarks (Hiding and Showing)")
+;; *** Filtering Bookmarks (Hiding and Showing) ***
+;;
+;; There are three ways to show only certain bookmarks.
+;;
+;; 1. Filter by bookmark type.
+;;
+;; 2. Filter bookmarks incrementally and temporarily, using pattern
+;; matching.
+;;
+;; 3. Filter out the marked or unmarked bookmarks.
+;;
+;; * Filtering by bookmark type
+;;
+;; The commands that show only bookmarks of a particular type are
+;; bound to keys that end in `S' (for "show"). For example, `I S'
+;; shows only Info bookmarks, and `X S' shows only temporary
+;; bookmarks.
+;;
+;; The type filter is reflected in the bookmark-list display title.
+;; It says `All Bookmarks' if no type filter is used. Otherwise it
+;; tells you what kind of bookmarks are listed: `Autonamed
+;; Bookmarks', `File and Directory Bookmarks', and so on.
+;;
+;; Note: It is only filtering by bookmark type that is remembered
+;; when you save a bookmark-list display state or you create a
+;; bookmark-list bookmark. See (@> "State-Restoring Commands and Bookmarks").
+;;
+;; * Filtering incrementally by pattern matching
+;;
+;; These commands show only bookmarks that in some way match a
+;; pattern (regexp) that you type. The bookmarks are filtered
+;; incrementally as you type the pattern. Hit any non-inserting
+;; key, such as `RET', to finish defining the pattern.
+;;
+;; The commands for this are bound to keys that start with `P' (for
+;; "pattern"). For example, `P B' shows only bookmarks whose names
+;; match the regexp, `P F' shows those whose file names match, `P
+;; A' shows those whose annotations match, and `P T' shows those
+;; that have one or more tags that match. (See (@> "Bookmark Tags"),
+;; above, for information about tags.)
+;;
+;; * Filtering based on marking
+;;
+;; Just as in Dired, you can use `% m' to mark the bookmarks that
+;; match a regexp. Then use `>' to show only the marked bookmarks.
+;; See (@> "Marking and Unmarking Bookmarks"), above.
+;;
+;; This method has the advantage that you can show the complement,
+;; the bookmarks that do *not* match the regexp, by using `<'
+;; instead of `>'. It also has the advantage that matching checks
+;; the combination of bookmark name and file name (use `M-t' to
+;; toggle showing file names).
+;;
+;;
+;;(@* "Only Visible Bookmarks Are Affected")
+;; *** Only Visible Bookmarks Are Affected ***
+;;
+;; Commands that operate on the current bookmark or on the marked or
+;; the unmarked bookmarks act only on bookmarks that are displayed
+;; (not hidden). This includes the commands that mark or unmark
+;; bookmarks. This means that you can easily define any given set of
+;; bookmarks.
+;;
+;; For example:
+;;
+;; Use `F S' to show only bookmarks associated with files.
+;; Use `% m' to mark those that match a particular regexp.
+;; Use `R S' to show only bookmarks that have regions.
+;; Use `m' to mark some of those region bookmarks individually.
+;; Use `.' to show all bookmarks.
+;; Use `t' to swap marked and unmarked (so unmarked are now marked)
+;; Use `D' to delete all of the marked bookmarks (after confirming)
+;;
+;; Together, steps 1-7 delete all file bookmarks that match the
+;; regexp and all region bookmarks that you selectively marked.
+;;
+;;
+;;(@* "Omitting Bookmarks from Display")
+;; *** Omitting Bookmarks from Display ***
+;;
+;; In sections (@> "Marking and Unmarking Bookmarks") and
+;; (@> "Filtering Bookmarks (Hiding and Showing)") you learned how
+;; to hide and show bookmarks in the bookmark list. This section is
+;; about a different kind of hiding, called "omitting".
+;;
+;; Omitted bookmarks are not shown in the bookmark list, no matter
+;; what filtering is used. The only way to show omitted bookmarks is
+;; to show all of them and only them, using `- S', which is bound to
+;; command `bmkp-bmenu-show-only-omitted'.
+;;
+;; Omitted bookmarks are still available even if they are not shown,
+;; and you can still jump to them (e.g. using `C-x r b'). You just
+;; don't see them in the bookmark list. And that's the reason for
+;; this feature: to hide those bookmarks that you don't care to see.
+;;
+;; One use for this feature is to hide the component bookmarks that
+;; make up a sequence bookmark (see
+;; (@> "Function, Sequence, Variable-List,... Bookmarks")). The
+;; default behavior when you create a sequence bookmark is in fact to
+;; omit its component bookmarks from the displayed list.
+;;
+;; You can omit any bookmarks by marking them and then using `- >'
+;; (`bmkp-bmenu-omit/unomit-marked'). If you are looking at the
+;; omitted bookmarks (after using `- S'), then `- >' un-omits the
+;; bookmarks marked there. Think of two complementary spaces: the
+;; normal bookmark list and the omitted bookmark list. When you use
+;; `- >', the marked bookmarks that are currently shown are moved to
+;; the opposite space.
+;;
+;; You can un-omit all of the omitted bookmarks at once, using `- U'
+;; (`bmkp-unomit-all'). You can also call this command from outside
+;; the bookmark-list display.
+;;
+;; Omitted bookmarks that are marked are generally not included when
+;; you use a command that acts on the marked bookmarks. However, if
+;; you use a negative prefix argument with the command then they are.
+;;
+;; For some commands this is relaxed so that any prefix arg has this
+;; effect. For other commands a non-negative prefix arg has a
+;; different effect. In some cases, a non-negative prefix arg has
+;; one effect and a non-positive prefix arg has the effect of
+;; including omitted marked bookmarks, so that a zero prefix arg has
+;; both effects. For any given command, consult the doc string for
+;; full information.
+;;
+;;
+;;(@* "Sorting Bookmarks")
+;; *** Sorting Bookmarks ***
+;;
+;; Filtering hides certain kinds of bookmarks. Sometimes, you want
+;; to see bookmarks of various kinds, but you want them to be grouped
+;; or sorted in different ways, for easy recognition, comparison, and
+;; access.
+;;
+;; Bookmarks shown in the bookmark list are sorted using the current
+;; value of option `bmkp-sort-comparer'. (If that is `nil', they are
+;; unsorted, which means they appear in reverse chronological order
+;; of their creation.)
+;;
+;; You can use `s s'... (repeat hitting the `s' key) to cycle among
+;; the various sort orders possible, updating the display
+;; accordingly. By default, you cycle among all available sort
+;; orders, but you can shorten the cycling list by customizing option
+;; `bmkp-sort-orders-for-cycling-alist'.
+;;
+;; You can also change directly to one of the main sort orders
+;; (without cycling) using `s >', `s n', `s f n', etc. There are
+;; many such predefined sort orders bound to keys with the prefix `s'
+;; - use `C-h m' or `?' for more info.
+;;
+;; `s >' – Sort marked (`>') before unmarked
+;; `s *' – Sort modified (`*') before unmodified
+;; `s 0' – Sort by bookmark creation date/time
+;; `s b' – Sort by last buffer or file access
+;; `s a' – Sort annotated (`a') before unannotated
+;; `s d' – Sort by last bookmark access date/time
+;; `s D' – Sort flagged (`D') before unflagged
+;; `s f d' – Sort by last local file access date/time
+;; `s f k' – Sort by local file kind: file, symlink, dir
+;; `s f n' – Sort by file name
+;; `s f s' – Sort by local file size
+;; `s f u' – Sort by last local file update (edit) date/time
+;; `s g' – Sort by Gnus thread: group, article, message.
+;; `s i' – Sort by Info manual, node, position
+;; `s k' – Sort by bookmark type (kind)
+;; `s n' – Sort by bookmark name
+;; `s t' – Sort tagged (`t') before untagged
+;; `s v' – Sort by visit frequency
+;;
+;; You can reverse the current sort direction (ascending/descending)
+;; using `s r'. Also, repeating any of the main sort-order commands
+;; (e.g. `s n') cycles among that order, the reverse, and unsorted.
+;;
+;; For a complex sort, which involves composing several sorting
+;; conditions, you can also use `s C-r' to reverse the order of
+;; bookmark sorting groups or the order within each group (depending
+;; on whether `s r' is also used). Try it, for example, together
+;; with sorting by bookmark kind (`s k').
+;;
+;; Be aware that `s C-r' can be a bit unintuitive. If it does not do
+;; what you expect or want, or if it confuses you, then don't use it
+;; ;-). (`s C-r' has no noticeable effect on simple sorting.)
+;;
+;; Remember that you can combine sorting with filtering different
+;; sets of bookmarks - bookmarks of different kinds (e.g. Info) or
+;; bookmarks that are marked or unmarked.
+;;
+;; Finally, you can easily define your own sorting commands and sort
+;; orders. See macro `bmkp-define-sort-command' and the
+;; documentation for option `bmkp-sort-comparer'. (Bookmark+ uses
+;; option `bmkp-sort-comparer'; it *ignores* vanilla Emacs option
+;; `bookmark-sort-flag'.)
+;;
+;; Of particular note is that you can interactively define commands
+;; that sort by a given list of tags - you use keys `T s' (command
+;; `bmkp-define-tags-sort-command') to do that. You are prompted for
+;; the tags to sort by. Bookmarks are sorted first according to
+;; whether they are tagged with the first tag, then the second tag,
+;; and so on. Otherwise, sorting is by bookmark name.
+;;
+;; The tags you specify are used, in order, in the name of the new
+;; command. For example, if you enter tags `alpha', `beta', and
+;; `gamma', in that order, then the sorting command created is
+;; `bmkp-bmenu-sort-alpha-beta-gamma'. The new command is saved in
+;; your bookmark commands file (`bmkp-bmenu-commands-file').
+;;
+;; Note that because you can add a new tag to all bookmarks that have
+;; some given set of tags, you can use that single (new) tag to
+;; represent the entire tag set. Sorting by that tag is then the
+;; same as sorting by the tag set. You can of course use overlapping
+;; sets in the composite sort command. You can, for example, sort
+;; first according to tag `tag1', which represents the set of tags
+;; `alpha', `beta', `gamma', `delta', and then sort according to tag
+;; `tag2', which represents the set of tags `beta', `delta'.
+;;
+;; See also (@> "Use Bookmark+ with Icicles") - the same technique is
+;; used in `Icicles' for sorting bookmarks as completion candidates.
+
+;;(@* "Bookmarks for Specific Files or Buffers")
+;; ** Bookmarks for Specific Files or Buffers **
+;;
+;; A bookmark typically records a position or a region in a file or
+;; buffer. Sometimes you are interested in accessing or examining
+;; only the bookmarks for particular files or buffers. For example,
+;; you might want to navigate among the bookmarks for the current
+;; buffer. Or you might want to search the regions recorded in the
+;; bookmarks for a particular file.
+;;
+;; For a bookmark, the recorded file and buffer name differ in that
+;; the file name is absolute. Bookmarks for buffer `foo.el' include
+;; all files named `foo.el', whereas bookmarks for file
+;; `/project1/lisp/foo.el' include only the files in that one
+;; directory.
+;;
+;; Another important difference is that when multiple buffers visit
+;; different files that have the same relative file name (i.e., in
+;; different directories), Emacs makes the buffer names unique by
+;; appending `<N>' as needed, where `N' is 2, 3,... When you create
+;; a bookmark, the current buffer name is recorded as the bookmark's
+;; buffer. If the current buffer is not visiting a file, then the
+;; bookmark created is a non-file bookmark. In that case, to use the
+;; bookmark later you must have a buffer of the same name
+;; (e.g. `foo.el<2>').
+;;
+;; Bookmark+ provides commands to handle these different use cases:
+;; specific files and specific buffers. The keys bound to these
+;; commands use `f' for file and `b' for buffer. In the
+;; bookmark-list display, the following keys affect the bookmarks for
+;; a particular file or buffer whose name you provide (with
+;; completion).
+;;
+;; * `= f M' and `= b M' - mark
+;; * `= f S' and `= b S' - show (only)
+;;
+;; For navigation, the following keys jump to bookmarks for
+;; particular files or buffers. (Use `C-x 4 j' for other-window.)
+;;
+;; * `C-x j ,,' - current buffer
+;; * `C-x j = f' and `C-x j = b' - specified file(s) or buffer(s)
+;;
+;; For the `=' keys you are prompted for one or more file names or
+;; buffer names.
+;;
+;; Finally, because the bookmarks in the current buffer can be of
+;; particular interest, `C-x x ,' opens the bookmark-list display for
+;; only those bookmarks. (`,' stands generally for "this-buffer" in
+;; Bookmark+ key bindings.)
+
+;;(@* "Cycling, Navigation List")
+;; ** "Cycling, Navigation List" **
+;;
+;; Using completion to jump to a bookmark is handy. It lets you
+;; choose a bookmark by its name and gives you direct ("random")
+;; access to it.
+;;
+;; Sometimes, however, you don't much care what a bookmark is named,
+;; and you want to cycle quickly among relatively few, related
+;; bookmarks. Obviously, the smaller the number of bookmarks in the
+;; set, the more convenient cycling is - with many bookmarks cycling
+;; can become tedious.
+;;
+;; An analogy: If your TV has lots of channels, then the channel
+;; up/down buttons on the remote control are not so useful: 32, 33,
+;; 34, ..., 79! Unless the channel you want happens to be near the
+;; current channel, cycling around a huge ring of channels is not the
+;; way to go. And just because your TV receives lots of channels
+;; does not mean that you watch them all or that you are equally
+;; interested in them all.
+;;
+;; Some TV remote controls have a feature that mitigates this
+;; problem. You can define a ring of favorite channels, and there
+;; are two additional buttons that let you cycle forward and backward
+;; around the ring, skipping the channels in between. The number of
+;; favorites is relatively small, so cycling is not tedious. More
+;; importantly, all of the channels in the ring are ones you are
+;; interested in.
+;;
+;; Extend this idea to allow for assigning different sets of channels
+;; to the favorites ring at different times: choose the ring you want
+;; at any time: sports, music, films, science, art, history, and so
+;; on. Add the possibility of sorting those sets in various ways, to
+;; further facilitate cycling, and you arrive at the idea behind the
+;; Bookmark+ navigation list.
+;;
+;; Another analogy is a music playlist. You can use Bookmark+ as a
+;; simple music player by bookmarking music files. Similarly, you
+;; can use Bookmark+ to create slideshows by bookmarking image files.
+;; Cycle the navigation list to move through the slide show.
+;;
+;; If you use MS Windows, you can take advantage of your existing
+;; file associations to open your bookmarks using the appropriate
+;; program - no need to define a new bookmark type and handler. See
+;; (@> "Bookmarking Files That You Cannot Visit with Emacs").
+;;
+;; Note: The default value of option `bmkp-use-region' is `t', not
+;; `cycling-too', which means that when you cycle to a bookmark its
+;; recorded region (if any) is not activated. This is probably what
+;; you want most of the time. Cycling is a repetitive action, and if
+;; you cycle to a bookmark with no recorded region then an already
+;; active region is just extended. Customize the value to
+;; `cycling-too' if you prefer that behavior.
+;;
+;;
+;;(@* "The Bookmark Navigation List")
+;; *** "The Bookmark Navigation List ***
+;;
+;; Bookmark+ is all about letting you define and manipulate sets of
+;; bookmarks. When a bookmark set can be used for cycling (as well
+;; as jumping) it is called the "navigation list" or "navlist", for
+;; short.
+;;
+;; In other words, Bookmark+ lets you cycle among any set of
+;; bookmarks. When you cycle, it is the set that currently
+;; constitutes the navigation list that is cycled.
+;;
+;; Here are two ways to define the navigation list:
+;;
+;; * `C-x x :' (`bmkp-choose-navlist-of-type') - As the set of all
+;; bookmarks of a certain type (`any' or empty input means use all
+;; bookmarks).
+;;
+;; * `C-x x B' (`bmkp-choose-navlist-from-bookmark-list') - As the
+;; set of all bookmarks corresponding to a bookmark-list bookmark,
+;; that is the bookmarks corresponding to a given recorded state of
+;; buffer `*Bookmark List*'.
+;;
+;; Each of these lets you choose a set of bookmarks using completion.
+;; For `C-x x :' you are prompted for the type of bookmark
+;; (e.g. `dired').
+;;
+;; For `C-x x B' you are prompted for the name of a bookmark-list
+;; bookmark that you created. But you can also choose the candidate
+;; `CURRENT *Bookmark List*' to capture the bookmarks that would be
+;; shown currently in the `*Bookmark List*' (even if the list is not
+;; displayed now). See (@> "State-Restoring Commands and Bookmarks")
+;; for information about bookmark-list bookmarks.
+;;
+;; If you do not define the navigation list before you start cycling,
+;; it is automatically defined as follows:
+;;
+;; * If you cycle using a current-file/buffer cycling key such as
+;; `C-x x down' (see (@> "Cycling in the Current File/Buffer"))
+;; then the bookmarks in the current file or buffer are used as the
+;; navlist.
+;;
+;; * Otherwise, a snapshot is taken of the the bookmarks currently in
+;; the global bookmark list (the value of variable
+;; `bookmark-alist') as the navlist.
+;;
+;; However the navlist is defined, it is important to remember this:
+;; it is a static snapshot of some set of bookmarks taken at a given
+;; time. Subsequent changes to the bookmark list that was copied are
+;; not reflected in the navlist. If you add a bookmark it will not
+;; be among those cycled. But see also
+;; (@> "Cycling Dynamic Sets of Bookmarks") for how to cycle dynamic
+;; sets.
+;;
+;; You can update the navlist at any time by taking another snapshot
+;; of the same bookmark list you used for the last snapshot. For the
+;; global bookmark list just use `C-x x : RET'. (You can of course
+;; bind that action to a shorter key sequence if you like.)
+;;
+;; Besides cycling among the bookmarks of the navlist (see next),
+;; once you have defined the navigation list you can use `C-x j N' or
+;; `C-x 4 j N' to jump to its bookmarks, as mentioned in section
+;; (@> "Different Types of Jump Commands").
+;;
+;; Note that just because you might have used `C-x x B' to define the
+;; navlist using a particular bookmark-list bookmark or the current
+;; `*Bookmark List*' state, that does not mean that the `*Bookmark
+;; List*' state at any given time necessarily reflects the navlist
+;; bookmarks. The two are separate. You can, however, open the
+;; `*Bookmark List*' so that it reflects the bookmarks currently in
+;; the navigation list, using `C-x x N' (`bmkp-navlist-bmenu-list').
+;;
+;;
+;;(@* "Cycling the Navigation List")
+;; *** "Cycling the Navigation List" ***
+;;
+;; So you choose a navigation list. How do you then cycle among its
+;; bookmarks?
+;;
+;; Commands `bmkp-next-bookmark' and `bmkp-previous-bookmark' cycle
+;; to the next and previous bookmark in the navigation list (with
+;; wraparound). (There are also other-window versions of these
+;; commands.)
+;;
+;; You can bind these to any keys you like, but it's obviously better
+;; to choose keys that are easily repeatable (e.g. by holding them
+;; pressed). Some people who are used to using MS Visual Studio
+;; might want to use `f2' and `S-f2' to cycle forward and backward.
+;;
+;; Bookmark+ does not define such key bindings, but you can. What it
+;; does is define repeatable keys on the `bookmark-map' keymap, which
+;; by default has prefix `C-x x'. To do this it binds similar
+;; commands that can be repeated by simply repeating the key-sequence
+;; suffix. These are the (default) keys:
+;;
+;; Forward: `C-x x f', `C-x x C-f', `C-x x right'
+;; Backward: `C-x x b', `C-x x C-b', `C-x x left'
+;;
+;; (If you use an Emacs version prior to Emacs 22, you cannot use
+;; this prefix-key repeatable feature.)
+;;
+;; In addition, if you use MS Windows then you can invoke the Windows
+;; `Open' action on each bookmark when you cycle, to act on its file
+;; using the program associated with the file type. This lets you
+;; play music or display images in a playlist or slideshow fashion.
+;; These are the keys to do that:
+;;
+;; Forward: `C-x x next' (PageDown key)
+;; Backward: `C-x x prior' (PageUp key)
+;;
+;; Being able to cycle among an arbitrary set of bookmarks is the
+;; most important feature of Bookmark+ cycling. The other important
+;; feature is that if the navigation list is defined by `*Bookmark
+;; List*' then the characteristics of that bookmark display are
+;; respected for navigation. Only the bookmarks visible in
+;; `*Bookmark List*' are included, and the `*Bookmark List*' sort
+;; order is used for navigation.
+;;
+;; So you can not only choose any set of bookmarks for cycling at any
+;; given time, you can also cycle among them in an order you choose.
+;; For example, if in the bookmark list display (`C-x x e' or `C-x r
+;; l') you show only those file bookmarks that belong to a given
+;; project, and you have them sorted by file size, then cycling moves
+;; among only those files, in file-size order.
+;;
+;; This is a main reason you will want to define bookmark-list
+;; bookmarks, which record a specific set of bookmarks and their sort
+;; order: to later choose given sets in different contexts for
+;; cycling.
+;;
+;;
+;;(@* "Cycling Dynamic Sets of Bookmarks")
+;; *** "Cycling Dynamic Sets of Bookmarks" ***
+;;
+;; The fact that the navlist is a static snapshot is a useful
+;; feature, but sometimes you might want to cycle among a particular
+;; dynamic set of bookmarks, that is, to have cycling take changes to
+;; the bookmark set into account automatically. For that, Bookmark+
+;; provides separate cycling commands for most types of bookmark.
+;;
+;; By default, these different kinds of cycling commands are not
+;; bound to any keys, with the exception of the commands for cycling
+;; the current fle or buffer. This exception includes cycling all
+;; bookmarks for the current file/buffer
+;; (see (@> "Cycling in the Current File/Buffer")
+;; and cycling only the highlighted bookmarks for the current
+;; file/buffer (see (@> "Using Highlighted Bookmarks")). Keys `C-x x
+;; down' and `C-x x C-down' are defined for these two kinds of
+;; current-buffer cycling.
+;;
+;; If you often want to cycle among the bookmarks of some other
+;; particular kind (e.g. only the autonamed bookmarks), then you can
+;; bind the relevant commands
+;; (e.g. `bmkp-next-autonamed-bookmark-repeat',
+;; `bmkp-previous-autonamed-bookmark-repeat', or their other-window
+;; versions) to handy keys. Otherwise, you can just use the cycling
+;; commands without binding them.
+;;
+;;
+;;(@* "Cycling in the Current File/Buffer")
+;; *** "Cycling in the Current File/Buffer" ***
+;;
+;; You can navigate the bookmarks in the current file or buffer by
+;; cycling as well as jumping. It is convenient to have dedicated
+;; keys for this, separate from the keys to cycle the navigation
+;; list. The following keys are defined, corresponding to commands
+;; `bmkp-next-bookmark-this-file/buffer-repeat' and
+;; `bmkp-previous-bookmark-this-file/buffer-repeat':
+;;
+;; Next: `C-x x n', `C-x x C-n', `C-x x down'
+;; Previous: `C-x x p', `C-x x C-p', `C-x x up'
+;;
+;; Starting with Emacs 23.3 (Emacs fix for bug #6256), you can also
+;; use the mouse wheel to cycle: `C-x x' then just rotate the wheel.
+;;
+;; Again, you can bind any keys you want to these commands
+;; (e.g. `f2', `S-f2'). If you do not need to use a prefix key, then
+;; bind commands `bmkp-next-bookmark-this-file/buffer' and
+;; `bmkp-previous-bookmark-this-file/buffer' (no -repeat).
+;;
+;; You can also cycle among just the highlighted bookmarks in the
+;; current file or buffer - see (@> "Using Highlighted Bookmarks").
+;;
+;; Cycling among bookmarks for the current file or buffer (whether
+;; all or only the highlighted ones) is dynamic: the current set of
+;; bookmarks is cycled, not a static snapshot taken at some point in
+;; past. The navlist is automatically updated to the current dynamic
+;; set each time you cycle. This is different from the usual cycling
+;; of the navlist, where it is taken as a static snapshot -
+;; see (@> "The Bookmark Navigation List").
+;;
+;; By default, you cycle among the bookmarks for the current file or
+;; buffer in order of their buffer positions, top to bottom. If you
+;; want a different order, you can customize option
+;; `bmkp-this-file/buffer-cycle-sort-comparer'.
+;;
+;; Alternatively, you can use `C-x x ,' to display the `*Bookmark
+;; List*' with only the current file/buffer's bookmarks, sort them
+;; there, and then use `C-x x B' to set the navigation list to
+;; `CURRENT *Bookmark List*'. In that case, you use the navlist
+;; cycling keys (e.g. `C-x x f', not `C-x x n'), and the cycled set
+;; is a static snapshot.
+;;
+;; Note that the keys mentioned here cycle bookmarks for the current
+;; file if visiting a file, or the current buffer otherwise. There
+;; are also commands (unbound to keys) for cycling bookmarks for the
+;; current file only or the current buffer only.
+;;
+;; The bookmarks for the current buffer are those that were created
+;; in a buffer of exactly the same name. If one buffer visits a file
+;; `foo.el', and another buffer visits a different file of the same
+;; name (i.e., in a different directory), the second buffer will have
+;; the name `foo.el<2>'. The buffer name is recorded when you create
+;; a bookmark. If you later use same-buffer cycling then the
+;; bookmarks cycled are only those created with the same buffer name
+;; as the current buffer.
+;;
+;; This is the reason why the `*-file/buffer*' commands are bound to
+;; keys. They are usually what you want. They try first to work
+;; with bookmarks for the same file as the current buffer, if it is
+;; visiting a file.
+
+;;(@* "Autonamed Bookmarks - Easy Come Easy Go")
+;; ** "Autonamed Bookmarks - Easy Come Easy Go" **
+;;
+;; Sometimes it is convenient to quickly create and delete bookmarks
+;; whose names you don't really care about. That is the purpose of
+;; "autonamed" bookmarks. An autonamed bookmark has a simple name
+;; provided automatically, and it does not record any region
+;; information - it records only a position. An autonamed bookmark
+;; is nevertheless an ordinary, persistent bookmark.
+;;
+;; `C-x x RET' creates a bookmark at point without prompting you for
+;; the name. It is named using the current buffer name preceded by
+;; the position in the buffer. For example, the default name of the
+;; autonamed bookmark in buffer `foo.el' at position 58356 is
+;; `000058356 foo.el'.
+;;
+;; When you jump to any bookmark, the actual destination can differ
+;; from the recorded position, because the buffer text might have
+;; changed. In that case, the position you jump to has been
+;; automatically relocated using the recorded bookmark context (some
+;; buffer text surrounding the original position).
+;;
+;; If option `bmkp-save-new-location-flag' is non-`nil' then, after
+;; jumping, the recorded position of the bookmark is automatically
+;; updated to reflect the new location jumped to. This is true for
+;; any bookmark.
+;;
+;; In the case of an autonamed bookmark, the bookmark name typically
+;; reflects the recorded position when you create it. And when you
+;; jump to it, both the name and the recorded position are updated to
+;; reflect the jump destination. So jumping to an autonamed bookmark
+;; keeps its persistent record in sync with the buffer location.
+;;
+;; You will thus notice that the names of autonamed bookmarks can
+;; change as you visit them (e.g. cycling). The bookmarks are
+;; automatically repositioned following their recorded contexts, and
+;; their names reflect that repositioning.
+;;
+;; It is only when you jump to a bookmark that it is repositioned
+;; this way, and only if needed. It is normal that some bookmarks
+;; become somewhat out of sync with their original positions as you
+;; edit the text in the buffer. In addition, if you highlight
+;; bookmarks then you will notice the highlighting move as you edit
+;; nearby text. The recorded bookmark has not changed, but its
+;; highlight has moved. The highlight moves more or less as if it
+;; were an Emacs marker. When you jump to the bookmark and it is thus
+;; updated, the highlight moves back to the recorded position,
+;; adjusted perhaps to fit the recorded context.
+;;
+;; `C-x x RET' is `bmkp-toggle-autonamed-bookmark-set/delete', and it
+;; does double duty. If an autonamed bookmark is under the cursor,
+;; then `C-x x RET' deletes it. Easy creation, easy deletion.
+;; Because of this toggle behavior, there is at most one autonamed
+;; bookmark at any given buffer position.
+;;
+;; `C-x x RET' has a third use: With a prefix argument, it prompts
+;; you to confirm the deletion of *ALL* autonamed bookmarks for the
+;; current buffer.
+;;
+;; (You can also use `C-x x delete' (that's the `delete' key), bound
+;; to `bmkp-delete-bookmarks', to delete individual bookmarks under
+;; the cursor or all bookmarks in the buffer. This is not limited to
+;; autonamed bookmarks.)
+;;
+;; In addition to `C-x x RET', you can create autonamed bookmarks
+;; using these commands:
+;;
+;; * `bmkp-set-autonamed-bookmark-at-line' - At a line beginning
+;; * `bmkp-set-autonamed-regexp-buffer' - At buffer matches
+;; * `bmkp-set-autonamed-regexp-region' - At region matches
+;; * `bmkp-occur-create-autonamed-bookmarks' (`C-c b' in `*Occur*') -
+;; At `occur' and `multi-occur' hits
+;;
+;; Autonamed bookmarks are normal bookmarks. In particular, they are
+;; persisted. If you do not care to persist them, you can ensure
+;; that they are automatically deleted by adding
+;; `bmkp-delete-autonamed-this-buffer-no-confirm' to
+;; `kill-buffer-hook' and `bmkp-delete-autonamed-no-confirm' to
+;; `kill-emacs-hook':
+;;
+;; (add-hook 'kill-buffer-hook
+;; 'bmkp-delete-autonamed-this-buffer-no-confirm)
+;; (add-hook 'kill-emacs-hook
+;; 'bmkp-delete-autonamed-no-confirm)
+;;
+;; You can customize the format of autonamed bookmarks using options
+;; `bmkp-autoname-bookmark-function' and `bmkp-autoname-format'.
+;;
+;; For example, if you want autonamed bookmarks to show the line and
+;; column numbers, in the form `L<num>,C<num> <buffer>', where <num>
+;; is a sequence of decimal digits and <buffer> is the buffer name,
+;; then you can use a function such as this as the value of
+;; `bmkp-autoname-bookmark-function':
+;;
+;; (defun my-auto-l+c-name (position)
+;; "Return a name for POSITION that uses line & column numbers."
+;; (let ((line (line-number-at-pos position))
+;; (col (save-excursion
+;; (goto-char position) (current-column))))
+;; (format "L%d,C%d %s" col line (buffer-name))))
+;;
+;; To enable Bookmark+ to recognize such bookmarks as autonamed, you
+;; would then set `bmkp-autoname-format' to the format specification
+;; "^L[0-9]+,C[0-9]+ %B", to match their names. Here, the `%B' is a
+;; Bookmark+ format specifier that corresponds to the buffer name.
+;;
+;; Recognizing the buffer name in an autonamed bookmark is important
+;; or commands that act only on autonamed bookmarks for a specific
+;; buffer. That includes commands `bmkp-autonamed-this-buffer-jump'
+;; and `bmkp-delete-all-autonamed-for-this-buffer'.
+;;
+;; You use the special format specifier `%B' for the buffer name,
+;; instead of just `%s', because the format can have multiple `%'
+;; sequences, and the buffer name could be anywhere in the bookmark
+;; name. Depending on the buffer, the buffer name could thus be
+;; confused with other text in the bookmark name, unless you use `%B'
+;; to show where it is. You can use just `%s' for it if there is no
+;; risk of ambiguity. (Use `%s' in `bmkp-autoname-bookmark-function'
+;; to insert the buffer name.)
+
+;;(@* "Temporary Bookmarks")
+;; ** Temporary Bookmarks **
+;;
+;; Autonamed bookmarks are easy-come-easy-go in the sense that `C-x x
+;; RET' either sets (creates) one or deletes the one under the
+;; cursor. But what about temporary bookmarks in general? What if
+;; you want only bookmarks that are temporary, that is, not saved to
+;; disk? Or what if you want certain kinds of bookmarks to always be
+;; temporary? Or what if you want to toggle whether particular
+;; bookmarks get saved automatically?
+;;
+;;
+;;(@* "Temporary Bookmarking Mode")
+;; *** Temporary Bookmarking Mode ***
+;;
+;; As always, you can control whether the bookmarks in the current
+;; bookmark list are saved automatically using option
+;; `bookmark-save-flag'. Remember that you can toggle this option
+;; using command `bmkp-toggle-saving-bookmark-file' (bound to `M-~'
+;; in the bookmark-list buffer). Remember too that you can at any
+;; time change the set of available bookmarks (the bookmark list),
+;; which means also changing the set of bookmarks that are
+;; susceptible to being saved.
+;;
+;; You could, for example:
+;;
+;; 1. Use `C-x x 0' (`bmkp-empty-file') to create a new, empty
+;; bookmark file.
+;;
+;; 2. Use `C-x x L' (`bmkp-switch-bookmark-file-create') to switch to
+;; using that new, empty bookmark file.
+;;
+;; 3. Use `M-x bmkp-toggle-saving-bookmark-file' to turn off
+;; auto-saving bookmarks to disk.
+;;
+;; This is essentially what the minor-mode toggle command
+;; `bmkp-temporary-bookmarking-mode' does. When in this minor mode,
+;; bookmarks that you create are stored on the new bookmark list,
+;; which is not automatically saved to disk. If you do not
+;; explicitly save it yourself then the bookmarks are lost when your
+;; Emacs session ends - they are only temporary.
+;;
+;; This command is bound to `M-L' in the bookmark-list display buffer
+;; (`*Bookmark List*'). The suffix `L' indicates that this has to do
+;; with loading a bookmark file. See (@> "Using Multiple Bookmark Files").
+;;
+;; In the bookmark-list display, temporary bookmarking mode is
+;; indicated in the mode line by `TEMPORARY Bookmarking' in place of
+;; `Bookmarks' as the mode name.
+;;
+;;
+;;(@* "Making Bookmarks Temporary")
+;; *** Making Bookmarks Temporary ***
+;;
+;; Instead of simply switching to a temporary bookmark list, so that
+;; *all* bookmarking is only temporary, you more often want to have
+;; some bookmarks be temporary while still ensuring that others get
+;; saved. Or you temporarily want all new bookmarks that you create
+;; and all bookmarks that you update to be temporary, without
+;; affecting other, unchanged bookmarks.
+;;
+;; You can control this at the level of individual bookmarks, types
+;; of bookmarks, or all bookmarks whenever they are set (created or
+;; updated).
+;;
+;; * At the individual-bookmark level, commands
+;; `bmkp-make-bookmark-temporary' and `bmkp-make-bookmark-savable'
+;; prompt you for a bookmark name and then set its
+;; temporary/savable status. Command
+;; `bmkp-toggle-temporary-bookmark' combines these commands,
+;; toggling the status for a given bookmark.
+;;
+;; In the bookmark list, this toggle is bound to `C-M-X'. There
+;; are also commands in the bookmark-list display to toggle the
+;; temporary/savable status of the marked bookmarks (`M-X'), to
+;; mark the temporary bookmarks (`X M'), and to show only the
+;; temporary bookmarks (`X S').
+;;
+;; * At the bookmark-type level, you can customize user option
+;; `bmkp-autotemp-bookmark-predicates'. It is a list of bookmark
+;; predicates - typically type predicates - that define which
+;; bookmarks are automatically made temporary whenever they are
+;; set.
+;;
+;; The default value includes the type predicates for autonamed
+;; bookmarks: `bmkp-autonamed-bookmark-p' and
+;; `bmkp-autonamed-this-buffer-bookmark-p'. This means that (only)
+;; autonamed bookmarks are made temporary whenever they are created
+;; or updated.
+;;
+;; The doc string for the option lists the predefined bookmark type
+;; predicates, but you can use any bookmark predicates.
+;;
+;; * Finally, you can toggle whether *all* bookmarks become temporary
+;; whenever they are created or updated, using command
+;; `bmkp-toggle-autotemp-on-set', which is bound globally to `C-x x
+;; x'.
+;;
+;; You can delete all such temporary bookmarks from the current
+;; bookmark list using command `bmkp-delete-all-temporary-bookmarks'
+;; (or by using `X M' to mark them in the bookmark-list display and
+;; then hitting `D' to delete thems).
+;;
+;; In the bookmark-list display (buffer `*Bookmark List*'), temporary
+;; bookmarks are indicated with the mark `X' in the same column where
+;; the annotation mark `a' would otherwise appear.
+
+;;(@* "Automatic Bookmarking")
+;; ** Automatic Bookmarking **
+;;
+;; You might find automatic bookmarking useful. The idea is that
+;; Emacs sets a bookmark for you automatically.
+;;
+;; Bookmark+ can do this either when you perform some action (besides
+;; explicitly bookmarking) or whenever you are idle for a given
+;; period of time (option `bmkp-automatic-bookmark-mode-delay').
+;;
+;;
+;;(@* "Automatic Bookmarking Using a Hook")
+;; *** Automatic Bookmarking Using a Hook ***
+;;
+;; To automatically set a bookmark whenever some hook is run, put
+;; function `bmkp-set-automatic-bookmark' on the hook. For example,
+;; to set a bookmark at a definition jumped to whenever you use
+;; Imenu, you can do this:
+;;
+;; (add-hook 'imenu-after-jump-hook #'bmkp-set-automatic-bookmark)
+;;
+;; The bookmark is an autonamed bookmark (see
+;; (@> "Autonamed Bookmarks - Easy Come Easy Go")).
+;;
+;;
+;;(@* "Automatic Idle-Period Bookmarking")
+;; *** Automatic Idle-Period Bookmarking ***
+;;
+;; Automatic idle-period bookmarking creates bookmarks at spots where
+;; you spend some time (idly). It uses
+;; `bmkp-set-automatic-bookmark', so the bookmarks created are
+;; autonamed (see (@> "Autonamed Bookmarks - Easy Come Easy Go")).
+;;
+;; How many such bookmarks would you want? And how close together?
+;; Bookmark+ tries to provide some user options that let you get the
+;; behavior you want. Except for
+;; `bmkp-automatic-bookmark-mode-delay' they apply to
+;; `bmkp-set-automatic-bookmark', so they affect both idle-period
+;; bookmarking and automatic bookmarking on a hook.
+;;
+;; In general, you probably don't want such bookmarks to be created
+;; too often or too close together. You probably don't care about
+;; the names of the bookmarks created, and you don't want to be
+;; interrupted to have to name them. You probably want automatic
+;; idle-period bookmarking to be per-buffer, but you might sometimes
+;; want to turn it on or off for all buffers. You might want more
+;; than one automatic bookmark on a given line, but probably not.
+;; Finally, you might or might not want such bookmarks to be
+;; temporary (current session only) or highlighted.
+;;
+;; Mode `bmkp-automatic-bookmark-mode' is a local minor mode, which
+;; means that it is buffer-specific. The command of the same name
+;; turns the mode on and off. When the mode is on, the minor-mode
+;; indicator ("lighter") `Auto-Bmk' is shown in the mode line for the
+;; buffer. You can customize this indicator (removing it, if you
+;; like), using option `bmkp-automatic-bookmark-mode-lighter'.
+;;
+;; Command `bmkp-global-automatic-bookmark-mode' turns on the mode in
+;; all buffers, that is, it is global, not local. Regardless of
+;; whether you use the mode locally or globally, a bookmark is
+;; created automatically only in the current buffer. That is, a
+;; buffer must be current (selected) for an automatic bookmark to be
+;; created there - it's not enough that the mode be enabled in the
+;; buffer.
+;;
+;; Option `bmkp-automatic-bookmark-set-function' defines the
+;; bookmark-setting function. By default, its value is
+;; `bmkp-set-autonamed-bookmark-at-line', which sets an autonamed
+;; bookmark at (the beginning of) the current line. If you want
+;; bookmarks to be created automatically then you typically want them
+;; to be autonamed, both because the name is unimportant and because
+;; setting an autonamed bookmark requires no interaction on your
+;; part. But you can use any setting function you like as the option
+;; value. (You can always rename an autonamed bookmark later, if you
+;; want to keep it and give it a meaningful name.)
+;;
+;; Option `bmkp-automatic-bookmark-min-distance' is the minimum
+;; number of characters between automatic bookmark positions. If the
+;; cursor is currently closer to some existing automatically created
+;; bookmark, then no automatic bookmark is set at point. If you set
+;; this to `nil' then there is no limit on how close the bookmarks
+;; can be. (But there is only one autonamed bookmark at any given
+;; position.)
+;;
+;; If you want automatically created bookmarks to be temporary (not
+;; saved to your bookmark file), then customize option
+;; `bmkp-autotemp-bookmark-predicates' so that it includes the kind
+;; of bookmarks that are set by
+;; `bmkp-automatic-bookmark-set-function'. For example, if automatic
+;; bookmarking sets autonamed bookmarks, then
+;; `bmkp-autotemp-bookmark-predicates' should include
+;; `bmkp-autonamed-bookmark-p' or
+;; `bmkp-autonamed-this-buffer-bookmark-p' (it includes both of these
+;; by default). Remember that you can toggle whether a given
+;; bookmark is temporary or savable, using `M-X' in the bookmark-list
+;; display (buffer `*Bookmark List*').
+;;
+;; If you want the bookmarks to be automatically highlighted, then
+;; customize option `bmkp-auto-light-when-set' to highlight bookmarks
+;; of the appropriate kind. For example, to highlight autonamed
+;; bookmarks set it to `autonamed-bookmark'.
+;;
+;; NOTE: If you use Emacs 20, then by default
+;; `bmkp-automatic-bookmark-mode' is global rather than local. The
+;; doc string tells you how to make it local instead. If you use
+;; Emacs 21, then `bmkp-automatic-bookmark-mode' is local but there
+;; is no global mode, `bmkp-global-automatic-bookmark-mode'. This is
+;; because Emacs 21 does not support `define-globalized-minor-mode'.
+;;
+;;
+;;(@* "Automatic Info Bookmarking")
+;; *** Automatic Info Bookmarking ***
+;;
+;; If you enable global minor mode `bmkp-info-auto-bookmark-mode',
+;; each Info node you visit is bookmarked automatically, using the
+;; default bookmark name, which is the Info manual name plus the node
+;; name. For example, node `Lisp Data Types' in the Elisp manual
+;; gives you a bookmark named `(elisp) Lisp Data Types'.
+;;
+;; With the mode enabled, when you visit an Info node an existing
+;; bookmark with the same name is always updated. If no such
+;; bookmark exists then a new one is created, provided option
+;; `bmkp-info-auto-type' has value `create-or-replace'. If it has
+;; value `update-only' then no new bookmark is created. The default
+;; option value is `update-only'. You can toggle the value using
+;; command `bmkp-toggle-info-auto-type'.
+;;
+;; With `bmkp-info-auto-bookmark-mode' enabled, even if you have
+;; created Info bookmarks with the default names manually, they are
+;; updated automatically. In particular, updating a bookmark
+;; increments the recorded number of visits to the Info node and the
+;; time of the last visit.
+;;
+;; You can sort bookmarks in the bookmark-list display by the time of
+;; last visit, using `s d', or by the number of visits, using `s v'.
+;;
+;; This gives you an easy way to see which parts of the manuals you
+;; have visited most recently and how much you have visited them.
+;; Showing only Info bookmarks gives you the effect of a persistent
+;; mini-manual of just the visited Info nodes. Turn the mode off
+;; anytime you do not want to record Info visits.
+;;
+;; Also useful in this context, though not related to bookmarking, is
+;; the ability to save your Info history persistently, so links to
+;; visited nodes are shown using a different face. This makes it
+;; easy to see which parts of a manual you have already looked at.
+;; (And checking a bookmark to a visited node shows you how much you
+;; have visited it.)
+;;
+;; If you use library `info+.el' then you have this complementary
+;; ability save your Info history list persistently. Just enable
+;; minor mode `Info-persist-history-mode'.
+
+;;(@* "Highlighting Bookmark Locations")
+;; ** Highlighting Bookmark Locations **
+;;
+;; You can highlight the location (destination) of a bookmark. For
+;; this feature you need library `bookmark+-lit.el' in addition to
+;; the other Bookmark+ libraries.
+;;
+;; You might never want to highlight a bookmark, or you might want to
+;; highlight most or even all bookmarks, or your use of highlighting
+;; might fall somewhere between. It depends on what kind of
+;; bookmarks you have and how you use them. Bookmark+ lets you
+;; choose. By default, no bookmarks are highlighted.
+
+;;(@* "Defining How to Highlight")
+;; ** Defining How to Highlight **
+;;
+;; By default, autonamed bookmarks are highlighted differently from
+;; non-autonamed bookmarks. Bookmark highlighting uses a style and a
+;; face. The available styles are these:
+;;
+;; * Region - Highlight the region, if a region bookmark
+;; * Line - Highlight line of the bookmark position
+;; * Position - Highlight character at bookmark position
+;; * Line Beginning - Highlight first character on line
+;; * Left Fringe - Highlight only the left fringe
+;; * Left Fringe + Line - Highlight the left fringe and the line
+;; * Right Fringe - Highlight only the right fringe
+;; * Right Fringe + Line - Highlight the right fringe and the line
+;;
+;; You can customize the default styles and faces to use for
+;; autonamed and non-autonamed bookmarks. You can also customize the
+;; fringe bitmaps to use.
+;;
+;; * `bmkp-light-autonamed' (face)
+;; * `bmkp-light-non-autonamed' (face)
+;; * `bmkp-light-autonamed-region' (face)
+;; * `bmkp-light-non-autonamed-region' (face)
+;; * `bmkp-light-style-autonamed' (option)
+;; * `bmkp-light-style-non-autonamed' (option)
+;; * `bmkp-light-style-autonamed-region' (option)
+;; * `bmkp-light-style-non-autonamed-region' (option)
+;; * `bmkp-light-left-fringe-bitmap' (option)
+;; * `bmkp-light-right-fringe-bitmap' (option)
+;;
+;; Note: A region, position, or line highlight acts more or less like
+;; an Emacs marker: it moves with the surrounding text. As you edit
+;; the text in the buffer, the highlighted location can thus become
+;; out of sync with the recorded position. This is normal. When you
+;; jump to the bookmark, its highlight is automatically repositioned
+;; to the recorded location, possibly adjusted according to the
+;; surrounding context.
+;;
+;; In addition to the default highlighting, which you can customize,
+;; you can set the highlighting for individual bookmarks and
+;; particular sets of bookmarks (overriding their default
+;; highlighting). These individual settings are saved as part of the
+;; bookmarks themselves.
+;;
+;; In the bookmark list display (buffer `*Bookmark List*'):
+;;
+;; * `H +' - Set the highlighting for this line's bookmark
+;; * `H > +' - Set the highlighting for the marked bookmarks
+;;
+;; Globally, you can use `M-x bmkp-set-lighting-for-bookmark' to set
+;; the highlighting for a given bookmark.
+;;
+;; Each of these commands prompts you (with completion) for the style
+;; and face to set, as well as for a condition that controls whether
+;; to highlight. Each of these is optional - just hit `RET' (empty
+;; input) at its prompt to skip setting it.
+;;
+;; The condition is an Emacs-Lisp sexp that is evaluated whenever an
+;; attempt is made to highlight the bookmark. Any resulting value
+;; except `:no-light' highlights the bookmark. The sexp can refer to
+;; the variables `this-bookmark' and `this-bookmark-name', whose
+;; values are the bookmark to be highlighted and its name,
+;; respectively.
+;;
+;; So, for example, if you wanted to be prompted each time before
+;; highlighting a certain bookmark you might set its highlighting
+;; condition to a sexp such as this:
+;;
+;; (or (y-or-n-p (format "Highlight `%s' " this-bookmark-name))
+;; :no-light)
+;;
+;; If you hit `n' at the prompt then `:no-light' is returned and the
+;; bookmark is not highlighted.
+;;
+;; In the bookmark-list display, a pink-background, one-character
+;; highlight is used next to each bookmark that has a highlight
+;; override wrt the default. You can see what that override setting
+;; is by using `C-u C-h RET' - look for the `lighting' entry in the
+;; bookmark definition.
+;;
+;;
+;;(@* "Highlighting On Demand")
+;; *** Highlighting On Demand ***
+;;
+;; You can highlight or unhighlight a bookmark or a set of bookmarks
+;; on demand.
+;;
+;; In the bookmark list (buffer `*Bookmark List*'):
+;;
+;; * `H H', `H U' - Highlight, unhighlight this line's bookmark
+;;
+;; * `H > H', `H > U' - Highlight, unhighlight the marked bookmarks
+;;
+;; Globally:
+;;
+;; * `C-x x C-u' - Unhighlight a highlighted bookmark at
+;; point or on the same line (in that order)
+;;
+;; * `C-x x h', `C-x x u' - Highlight, unhighlight a bookmark in the
+;; current buffer (with completion).
+;;
+;; * `C-x x H', `C-x x U' - Highlight, unhighlight bookmarks:
+;;
+;; With plain `C-u': all bookmarks
+;;
+;; With `C-u C-u': navigation-list bookmarks
+;;
+;; Otherwise, bookmarks in current buffer:
+;; No prefix arg: all bookmarks
+;; Prefix arg > 0: autonamed bookmarks
+;; < 0: non-autonamed bookmarks
+;;
+;; The default bookmark for `C-x x u' is the same bookmark that is
+;; unhighlighted by `C-x x C-u': a (highlighted) bookmark at point
+;; (preferably) or on the same line. The latter key binding just
+;; saves you having to hit `RET' to pick the default.
+;;
+;; When you use `C-x x h', you can use a prefix argument to override
+;; both the default highlighting and any highlighting that is
+;; recorded for the bookmark itself. You are prompted for the style
+;; or face to use:
+;;
+;; * Negative arg: prompted for style
+;; * Non-negative arg: prompted for face
+;; * Plain `C-u': prompted for style and face
+;;
+;;
+;;(@* "Highlighting Automatically")
+;; *** Highlighting Automatically ***
+;;
+;; You can also highlight automatically, whenever you set (create) a
+;; bookmark or jump to one. This is controlled by these options:
+;;
+;; * `bmkp-auto-light-when-set'
+;; * `bmkp-auto-light-when-jump'
+;;
+;; You can choose any of these values for either option:
+;;
+;; * Autonamed bookmark
+;; * Non-autonamed bookmark
+;; * Any bookmark
+;; * Autonamed bookmarks in buffer
+;; * Non-autonamed bookmarks in buffer
+;; * All bookmarks in buffer
+;; * None (no automatic highlighting) - the default
+;;
+;; The first three values highlight only the bookmark being set or
+;; jumped to.
+;;
+;; Be aware that, depending on the setting, highlighting can take a
+;; while.
+
+;;(@* "Using Highlighted Bookmarks")
+;; ** Using Highlighted Bookmarks **
+;;
+;; Once you have highlighted bookmarks, what can you do with them?
+;; Obviously, the highlighting can help you distinguish and find
+;; bookmarks visually. But highlighting also serves as yet another
+;; way to define sets: the highlighted vs unhighlighted bookmarks.
+;;
+;; Any command that operates on a set of bookmarks can be applied to
+;; one or the other of these two sets. Bookmark+ defines only a few
+;; such operations, but you can easily define others.
+;;
+;; In addition to such specific commands, you can also apply general
+;; operations to the highlighted or unhighlighted bookmarks, using
+;; the bookmark-list display (`*Bookmark List*'). `H S' shows only
+;; the bookmarks that are currently highlighted, and `H M' marks
+;; them. You can then perform any of the available bookmark-list
+;; operations on them.
+;;
+;; Globally, you can use these keys:
+;;
+;; * `C-x x =' - List the bookmarks that are
+;; highlighted at point. With a
+;; prefix arg, show the full data.
+;;
+;; * `C-x j h', `C-x 4 j h' - Jump to a highlighted bookmark.
+;; Only highlighted bookmarks are
+;; completion candidates.
+;;
+;; * `C-x x C-down', `C-x x C-up' - Cycle to the next and previous
+;; highlighted bookmark.
+
+;;(@* "Bookmark Links")
+;; ** Bookmark Links **
+;;
+;; You can use command `bmkp-insert-bookmark-link' to create links in
+;; any Emacs text that jump to particular bookmarks when you follow
+;; them (by hitting `RET' or clicking `mouse-2'). If you hit `?' or
+;; double-click `mouse-1' on such a bookmark link then the bookmark
+;; is described, showing the same information as `C-h M'
+;; (`bmkp-describe-bookmark').
+;;
+;; You are prompted for the bookmark to link. If the region is
+;; active and nonempty then the link is put on its text. Otherwise,
+;; you are prompted for the link text, which is inserted. The
+;; default link text is the bookmark name in this case.
+;;
+;; The bookmark linked can be of any type.
+;;
+;; This simple feature lets you easily create "launching pads" for
+;; different sets of bookmarks: buffers or files that consist of
+;; bookmark links and any other text you like. This gives you yet
+;; another way to organize bookmarks (and so also the files,
+;; directories, etc. that they target).
+;;
+;; If you also use library `font-lock+.el' then the links appear with
+;; face `link', even in a font-locked buffer. (Library
+;; `font-lock+.el' just provides this feature of allowing
+;; non-font-lock highlighting in a font-locked buffer. See
+;; https://lists.gnu.org/archive/html/emacs-devel/2014-08/msg00540.html.)
+;;
+;; The links you create this way are not persistent, but you can of
+;; course re-create them using Lisp.
+;;
+;;
+;;(@* "Org Mode Links that Jump To Bookmarks")
+;; *** Org Mode Links that Jump To Bookmarks ***
+;;
+;; You can also easily define Org-mode links that jump to bookmarks.
+;; These links are persistent. Again, the bookmark linked can be of
+;; any type.
+;;
+;; You can use the standard Org command `org-store-link' (`C-c l') in
+;; buffer `*Bookmark List*' to store a link to the bookmark at point.
+;; (This is also item `Store Org Link' in the mouse-3 popup menu.)
+;;
+;; Outside buffer `*Bookmark List*' you can use command
+;; `bmkp-store-org-link' to store a link to any bookmark. You are
+;; prompted for the bookmark name. You can even enter the name of a
+;; bookmark that does not yet exist. (This is also item `Store Org
+;; Link To...' on menu `Bookmarks'.)
+;;
+;; If you use a numeric prefix arg with either command then the
+;; bookmark link stored will be for jumping to the bookmark in the
+;; same window. Without a numeric prefix arg, the link will use
+;; another window. (Org mode defines other behaviors for non-numeric
+;; prefix args, such as `C-u C-u'.)
+;;
+;; As usual, to insert a bookmark link, you use command
+;; `org-insert-link'. Enter the name of the target bookmark at the
+;; prompt. In Org mode you can use the usual Org key bindings to
+;; follow the link. In any mode you can use standard Org command
+;; `org-open-at-point-global' (not bound to a key by default).
+
+;;(@* "Bookmark Menus")
+;; ** Bookmark Menus **
+;;
+;; Two menu-bar menus for Bookmark+ have already been mentioned:
+;;
+;; * Menu `Bookmark+', for the bookmark-list display (buffer
+;; `*Bookmark List*').
+;;
+;; * Menu `Bookmarks', which is typically a submenu of the menu-bar
+;; `Edit' menu (available also with vanilla Emacs but enhanced by
+;; Bookmark+).
+;;
+;; Access to bookmarks for the currently visited file or current
+;; buffer is available as a `Bookmarks Here' submenu of the
+;; major-mode menu-bar menu in modes Info and Buffer-Menu, if option
+;; `bmkp-add-bookmarks-here-menu-flag' is non-`nil'.
+;;
+;; The menu items let you cycle among bookmarks in the current
+;; file/buffer or access the bookmark-list display for only those
+;; bookmarks.
+;;
+;; If you use library Dired+ then the same access is available in
+;; Dired mode on menu-bar menu `Dir' > `Bookmark' > `Here'.
+;;
+;; If you use library Imenu+ then the same access is available in an
+;; Imenu submenu `Bookmarks Here'. In this case there are also menu
+;; items to jump to each bookmark in the file/buffer. For Imenu,
+;; display of the menu is controlled by option
+;; `imenup-show-bookmarks-flag'.
+
+;;(@* "Use Bookmark+ with Icicles")
+;; ** Use Bookmark+ with Icicles **
+;;
+;; `Icicles' (https://www.emacswiki.org/emacs/Icicles) enhances your
+;; use of Bookmark+ in several ways.
+;;
+;; When jumping to a bookmark, you can narrow the completion
+;; candidates to bookmarks of a particular type (e.g. Info, using
+;; `C-M-i'; remote, using `C-M-@'; region, using `C-M-r'). You can
+;; narrow again (and again), to another bookmark type, to get the
+;; intersection (e.g. remote Info bookmarks that define a region).
+;;
+;; You can also narrow against different bookmark-name patterns
+;; (e.g. regexps) - so-called "progressive completion". And take the
+;; complement (e.g., bookmarks whose names do not match
+;; `foo.*2010.*bar'). (This is not special to bookmarks; it is
+;; standard `Icicles' practice.)
+;;
+;; In Icicle mode, several of the Bookmark+ keys are remapped to
+;; corresponding `Icicles' multi-commands. A bookmark jump key thus
+;; becomes a bookmarks browser. For example, `C-x j d' browses among
+;; any number of Dired bookmarks.
+;;
+;; A single key can set a bookmark or visit bookmarks. This key is
+;; whatever command `bmkp-bookmark-set-confirm-overwrite' would
+;; normally be bound to - e.g. `C-x r m'. A prefix arg controls what
+;; it does. If negative (`M--'), jump to (browse) bookmarks.
+;; Otherwise, set a bookmark using
+;; `bmkp-bookmark-set-confirm-overwrite', as follows:
+;;
+;; * No prefix arg: Prompt for the bookmark name. The candidates are
+;; bookmarks in the current buffer (or all bookmarks if there are
+;; none in the current buffer).
+;;
+;; * (Non-negative) numeric prefix arg: No prompt. Use the buffer
+;; name plus the text of the region (if active) or the current line
+;; as the bookmark name. Quickest way to set a bookmark.
+;;
+;; * Plain `C-u': Prompt for name, no bookmark overwrite.
+;;
+;; During completion of a bookmark name, many features of the
+;; bookmark-list display (see (@> "The Bookmark List Display")) are
+;; available on the fly. Buffer `*Completions*' acts like a dynamic
+;; version of `*Bookmark List*':
+;;
+;; * Candidates are highlighted in the `*Completions*' window
+;; according to their bookmark type.
+;;
+;; * Candidates are `Icicles' multi-completions with up to three
+;; parts:
+;;
+;; a. the bookmark name
+;; b. the bookmark file or buffer name
+;; c. any tags
+;;
+;; You can match any or all of the parts. For example, you can
+;; match bookmarks that have tags by typing this regexp:
+;;
+;; C-M-j . * C-M-j S-TAB
+;;
+;; Each `C-M-j' inserts `^G\n', which is `icicle-list-join-string',
+;; the string used to join the parts. This regexp says, "match the
+;; completion candidates that have all three parts (two join
+;; strings)", hence some tags.
+;;
+;; You can turn off the use of multi-completion candidates for
+;; subsequent commands, so only bookmark names are used, by hitting
+;; `M-m' in the minibuffer. You can think of this as similar to
+;; using `M-t' in `*Bookmark List*' to toggle showing file names.
+;; You can make not showing files and tags the default behavior by
+;; customizing `icicle-show-multi-completion-flag'.
+;;
+;; * You can sort completion candidates using the Bookmark+ sort
+;; orders. Use `C-,' to cycle among sort orders.
+;;
+;; * You can use `Icicles' candidate-help keys (`C-M-RET',
+;; `C-M-down', etc.) to get detailed information about the current
+;; bookmark candidate. `C-u C-M-RET' shows the complete, internal
+;; info defining the bookmark. And without doing anything, summary
+;; info about the current candidate is available in the mode line
+;; of buffer `*Completions*'.
+;;
+;; * You can use `Icicles' candidate-action keys (`C-RET',
+;; `C-mouse-2', `C-down', etc.) to visit any number of bookmarks.
+;; For example, holding down `C-down' cycles among the current
+;; bookmark candidates, opening each in turn.
+;;
+;; * You can use `S-delete' to delete the bookmark named by the
+;; current candidate. You can delete any number of bookmarks this
+;; way, during a single invocation of a bookmark command.
+;;
+;; * You can define `Icicles' sets of bookmarks, persistent or not,
+;; and act on their members in various ways.
+;;
+;; During file-name completion, you can do any of the following on
+;; the fly:
+;;
+;; * Jump to one or more file bookmarks, using `C-x m'.
+;;
+;; * Create one or more autofile bookmarks, using `C-x a a'.
+;;
+;; * Add tags to one or more files or directories (autofile
+;; bookmarks), using `C-x a +'.
+;;
+;; * Remove tags from one or more files or directories (autofile
+;; bookmarks), using `C-x a -'.
+;;
+;; There are 25 Icicles commands for searching bookmark destinations!
+;; The most general is `icicle-search-bookmark'. Others let you
+;; search specific kinds of bookmarks, or bookmarks having various
+;; combinations of tags.
+;;
+;; During Icicles search (of anything, not just a bookmark
+;; destination), you can save sets of completion candidates, which
+;; means sets of search hits, as bookmarks. And Icicles lets you use
+;; set operations (complement, union, intersection, difference etc.)
+;; on the current set of search hits.
+;;
+;; When you "jump" to an Icicles search-hits bookmark, its recorded
+;; search hits are restored to Icicles search as completion
+;; candidates, either replacing the current candidates or adding to
+;; them.
+;;
+;; You can thus save and later return to different sets of search
+;; results using different bookmarks. You can "jump" to an Icicles
+;; search-hits bookmark during any Icicles search, whether you search
+;; a file, a buffer, multiple files, or multiple buffers.
+
+;;(@* "Bookmark Compatibility with Vanilla Emacs (`bookmark.el')")
+;; ** Bookmark Compatibility with Vanilla Emacs (`bookmark.el') **
+;;
+;; Bookmark+ is generally compatible with GNU Emacs versions 20 and
+;; later. You can use bookmarks with Bookmark+ regardless of whether
+;; they were created using Bookmark+ or vanilla Emacs (i.e., library
+;; `bookmark.el').
+;;
+;; But for best results, if you have bookmarks that you created using
+;; Bookmark+ then use Bookmark+, not vanilla Emacs, to access them.
+;; This section provides details.
+;;
+;; Set user option `bmkp-propertize-bookmark-names-flag', depending
+;; on your usage scenario (the default is `t' for Emacs 21 and later,
+;; `nil' for Emacs 20):
+;;
+;; 1. Set it to `nil' if you will often be going back and forth
+;; between using Bookmark+ and using vanilla Emacs. (Do this also
+;; if you use Emacs 20.)
+;;
+;; 2. Set it to non-`nil' if you instead always use only Bookmark+
+;; (with Emacs 21 or later), or you use vanilla Emacs only to jump
+;; to bookmarks but never to update or create bookmarks.
+;;
+;; #1 is VERY IMPORTANT. You can lose data if you do not respect it.
+;;
+;; The reason for rule #1 is this: When the option is non-`nil'
+;; Bookmark+ writes bookmarks to your bookmark file in a format that
+;; can be read and used by vanilla Emacs (21 and later) but which
+;; vanilla Emacs then saves as unreadable. If the option value is
+;; `nil' there is no such problem.
+;;
+;; #2 is not a requirement. It is just a good idea, to be able to
+;; take better advantage of Bookmark+. If you set the option to
+;; `nil' then you cannot use multiple bookmarks that have the same
+;; name. Vanilla Emacs does not make good use of such critters, but
+;; Bookmark+ does. Having multiple bookmarks with the same name is
+;; particularly useful for autofiles. It means you can have
+;; different autofiles in different directories but with the same
+;; name. See (@> "Autofile Bookmarks").
+;;
+;; Here is what happens when `bmkp-propertize-bookmark-names-flag' is
+;; non-nil:
+;;
+;; Besides its name, which is what you see and use most of the time,
+;; a bookmark contains other information such as the target location,
+;; textual context hints, and last access time. Non-`nil'
+;; `bmkp-propertize-bookmark-names-flag' has no effect on vanilla
+;; Emacs, but it causes Bookmark+ to put the full bookmark
+;; information on the bookmark name as a text property.
+;;
+;; The name thus encapsulates all of the information contained in the
+;; full bookmark of which it is part. Knowing the name is then
+;; enough to know everything about the bookmark. Part of the
+;; bookmark (its name) refers to the whole of it. In Lisp this
+;; self-reference is implemented using circular structures.
+;;
+;; When Bookmark+ saves such circular structures to your bookmark
+;; file, if the option is non-`nil' then it takes care to do so in
+;; such a way that they can be read in again when your bookmark file
+;; is loaded. In Lisp terms, it binds `print-circle' to non-`nil'
+;; when it writes your bookmarks. If the option value is `nil' then
+;; the circularity (self-reference) is removed before your bookmarks
+;; are saved. Either way, the file is readable.
+;;
+;; Vanilla Emacs (21 and later) has no problem reading your bookmark
+;; file if it contains such circular structures. But if you then use
+;; it to save the file again, the Lisp code it writes has invalid
+;; Lisp `read' syntax (because it does not remove the circularity but
+;; it also does not bind `print-circle' to non-`nil').
+;;
+;; If that happens, the result is a bookmark file that is UNREADABLE.
+;; It cannot be loaded into either vanilla Emacs or Bookmark+. If
+;; you do not have an uncorrupted backup version of the file to
+;; revert to, then you will need to edit it by hand to clean it up.
+;;
+;; So do not let that happen to you! For best results use only
+;; Bookmark+ to access bookmarks created using Bookmark+.
+;;
+;; If you must use vanilla Emacs with your bookmarks, then make sure
+;; they are not saved by Bookmark+ with the option non-`nil': Using
+;; Bookmark+, set the option to `nil' and then save the file.
+;;
+;; That is:
+;;
+;; 1. `M-x set-variable bmkp-propertize-bookmark-names-flag nil',
+;; to stop using propertized bookmark names.
+;; 2. `C-x x e' or `C-x r l', to display the bookmark list.
+;; 3. `g', to refresh the display.
+;; 4. `S', to save the bookmark list.
+;; 5. `M-x bmkp-save-menu-list-state', to save the display state.
+;;
+;; Then you can use your bookmark file with vanilla Emacs (but
+;; without the possibility of having multiple bookmarks with the same
+;; name).
+;;
+;; Note that when the option value is non-`nil', propertized bookmark
+;; names are saved not only to your bookmark file but also to any
+;; full snapshots you create of the bookmark-list display state using
+;; command `bmkp-bmenu-define-full-snapshot-command' (`C-c C-C', aka
+;; `C-c C-S-c'). See (@> "State-Restoring Commands and Bookmarks").
+
+;;(@* "New Bookmark Structure")
+;; ** New Bookmark Structure **
+;;
+;; The bookmark data structure, variable `bookmark-alist', has been
+;; enhanced to support new bookmark types. For a description of this
+;; enhanced structure, use `C-h v bookmark-alist'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;; You need not load this file. It contains only documentation.
+
+(provide 'bookmark+-doc)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; bookmark+-doc.el ends here
+
--- /dev/null
+;;; bookmark+-key.el --- Bookmark+ key and menu bindings.
+;;
+;; Filename: bookmark+-key.el
+;; Description: Bookmark+ key and menu bindings.
+;; Author: Drew Adams
+;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com")
+;; Copyright (C) 2010-2022, Drew Adams, all rights reserved.
+;; Created: Fri Apr 1 15:34:50 2011 (-0700)
+;; Last-Updated: Fri Jan 14 12:49:18 2022 (-0800)
+;; By: dradams
+;; Update #: 980
+;; URL: https://www.emacswiki.org/emacs/download/bookmark%2b-key.el
+;; Doc URL: https://www.emacswiki.org/emacs/BookmarkPlus
+;; Keywords: bookmarks, bookmark+, placeholders, annotations, search, info, url, eww, w3m, gnus
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x, 26.x
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; The Bookmark+ libraries are these:
+;;
+;; `bookmark+.el' - main (driver) library
+;; `bookmark+-mac.el' - Lisp macros
+;; `bookmark+-lit.el' - (optional) code for highlighting bookmarks
+;; `bookmark+-bmu.el' - code for the `*Bookmark List*' (bmenu)
+;; `bookmark+-1.el' - other (non-bmenu) required code
+;; `bookmark+-key.el' - key and menu bindings (this file)
+;;
+;; `bookmark+-doc.el' - documentation (comment-only file)
+;; `bookmark+-chg.el' - change log (comment-only file)
+;;
+;; The documentation (in `bookmark+-doc.el') includes how to
+;; byte-compile and install Bookmark+. The documentation is also
+;; available in these ways:
+;;
+;; 1. From the bookmark list (`C-x r l'):
+;; Use `?' to show the current bookmark-list status and general
+;; help, then click link `Doc in Commentary' or link `Doc on the
+;; Web'.
+;;
+;; 2. From the Emacs-Wiki Web site:
+;; https://www.emacswiki.org/emacs/BookmarkPlus.
+;;
+;; 3. From the Bookmark+ group customization buffer:
+;; `M-x customize-group bookmark-plus', then click link
+;; `Commentary'.
+;;
+;; (The commentary links in #1 and #3 work only if you have library
+;; `bookmark+-doc.el' in your `load-path'.)
+;;
+;;
+;; User options defined here:
+;;
+;; `bmkp-add-bookmarks-here-menu-flag',
+;; `bmkp-bookmark-map-prefix-key', `bmkp-jump-map-prefix-key',
+;; `bmkp-jump-other-window-map-prefix-key'.
+;;
+;; Non-interactive functions defined here:
+;;
+;; `bmkp-bookmark-data-from-record',
+;; `bmkp-bookmark-name-from-record',
+;; `bmkp-exists-bookmark-satisfying-p',
+;; `bmkp-exists-this-file/buffer-bookmarks-p',
+;; `bmkp-set-map-prefix-key', `bookmark-name-from-full-record',
+;; `bookmark-name-from-record'.
+;;
+;; Internal variables defined here:
+;;
+;; `bmkp-annotate-map', `bmkp-annotate-menu', `bmkp-here-menu',
+;; `bmkp-bookmarks-here-menu-command-entries',
+;; `bmkp-find-file-menu', `bmkp-highlight-menu', `bmkp-jump-map',
+;; `bmkp-jump-menu', `bmkp-jump-other-window-map',
+;; `bmkp-jump-tags-menu', `bmkp-set-map', `bmkp-tags-map',
+;; `bmkp-tags-menu'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; *This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;
+
+(eval-when-compile
+ (or (condition-case nil
+ (load-library "bookmark+-mac") ; Use load-library to ensure latest .elc.
+ (error nil))
+ (require 'bookmark+-mac))) ; Require, so can load separately if not on `load-path'.
+;; bmkp-menu-bar-make-toggle
+
+(eval-when-compile (require 'cl)) ;; case
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Quiet the byte-compiler
+
+(defvar bmkp-bmenu-buffer) ; In `bookmark+.el'
+(defvar grep-mode-map)
+
+
+;; Prefix keys.
+;;
+;; These two maps are always on `bookmark-map', wherever it is: `bmkp-set-map', `bmkp-tags-map'.
+;;
+(defun bmkp-set-map-prefix-key (pref-keys-option keys)
+ "Set prefix key option SYMBOL to key-sequence VALUE."
+ (set pref-keys-option keys)
+ (let* ((g-map (current-global-map))
+ (b-map (case pref-keys-option
+ (bmkp-bookmark-map-prefix-keys 'bookmark-map)
+ (bmkp-jump-map-prefix-keys 'bmkp-jump-map)
+ (bmkp-jump-other-window-map-prefix-keys 'bmkp-jump-other-window-map))))
+ (dolist (key (where-is-internal b-map g-map))
+ (define-key g-map key nil))
+ (dolist (key keys)
+ (define-key g-map key b-map))))
+
+(defcustom bmkp-bookmark-map-prefix-keys (list (kbd "C-x x"))
+ "Prefix keys for `bookmark-map' in `current-global-map'.
+Each value of the list is a prefix key bound to keymap `bookmark-map'."
+ :type (if (> emacs-major-version 21)
+ '(repeat (key-sequence :tag "Key" :value [ignore]))
+ '(repeat (restricted-sexp
+ :tag "Key"
+ :match-alternatives ((lambda (x) (or (stringp x) (vectorp x))))
+ :value [ignore])))
+ :set 'bmkp-set-map-prefix-key
+ :group 'bookmark-plus)
+
+(defcustom bmkp-jump-map-prefix-keys (list (kbd "C-x j"))
+ "Prefix keys for `bmkp-jump-map' in `current-global-map'.
+Each value of the list is a prefix key bound to keymap
+`bmkp-jump-map'."
+ :type (if (> emacs-major-version 21)
+ '(repeat (key-sequence :tag "Key" :value [ignore]))
+ '(repeat (restricted-sexp
+ :tag "Key"
+ :match-alternatives ((lambda (x) (or (stringp x) (vectorp x))))
+ :value [ignore])))
+ :set 'bmkp-set-map-prefix-key
+ :group 'bookmark-plus)
+
+(defcustom bmkp-jump-other-window-map-prefix-keys (list (kbd "C-x 4 j"))
+ "Prefix keys for `bmkp-jump-other-window-map' in `current-global-map'.
+Each value of the list is a prefix key bound to keymap
+`bmkp-jump-other-window-map'."
+ :type (if (> emacs-major-version 21)
+ '(repeat (key-sequence :tag "Key" :value [ignore]))
+ '(repeat (restricted-sexp
+ :tag "Key"
+ :match-alternatives ((lambda (x) (or (stringp x) (vectorp x))))
+ :value [ignore])))
+ :set 'bmkp-set-map-prefix-key
+ :group 'bookmark-plus)
+
+(defcustom bmkp-add-bookmarks-here-menu-flag nil
+ "Non-nil means add a `Bookmarks Here' menu to some menu-bar menus.
+The menu is added only if there are in fact bookmarks for the current
+buffer or file. The default value is nil because checking whether
+there are such bookmarks can take a little time."
+ :type 'boolean :group 'bookmark-plus)
+
+
+
+;; Some general Renamings.
+;;
+;; 1. Fix incompatibility introduced by gratuitous Emacs name change.
+;;
+(cond ((and (fboundp 'bookmark-name-from-record) (not (fboundp 'bookmark-name-from-full-record)))
+ (defalias 'bookmark-name-from-full-record 'bookmark-name-from-record))
+ ((and (fboundp 'bookmark-name-from-full-record) (not (fboundp 'bookmark-name-from-record)))
+ (defalias 'bookmark-name-from-record 'bookmark-name-from-full-record)))
+
+;; 2. The vanilla name of the first is misleading, as it returns only the cdr of the record.
+;; The second is for consistency.
+;;
+(defalias 'bmkp-bookmark-data-from-record 'bookmark-get-bookmark-record)
+(defalias 'bmkp-bookmark-name-from-record 'bookmark-name-from-full-record)
+
+
+;; Quiet the byte-compiler
+(defvar bmkp-bmenu-menubar-menu) ; In `bookmark+-bmu.el'.
+(defvar bmkp-bmenu-toggle-menu) ; In `bookmark+-bmu.el'.
+(defvar bmkp-crosshairs-flag) ; In `bookmark+-1.el'.
+(defvar bmkp-eww-replace-keys-flag) ; In `bookmark+-1.el' (Emacs 25+).
+(defvar bmkp-prompt-for-tags-flag) ; In `bookmark+-1.el'.
+(defvar bmkp-save-new-location-flag) ; In `bookmark+-1.el'.
+(defvar diredp-bookmark-menu) ; In `dired+.el'.
+(defvar eww-mode-map) ; In `eww.el' (Emacs 24.4+).
+(defvar gnus-summary-mode-map) ; In `gnus-sum.el'.
+(defvar Info-mode-map) ; In `info.el'.
+(defvar Info-mode-menu) ; In `info.el'.
+(defvar Man-mode-map) ; In `man.el'.
+(defvar mouse-wheel-down-event) ; In `mwheel.el'.
+(defvar mouse-wheel-up-event) ; In `mwheel.el'.
+(defvar w3m-minor-mode-map) ; In `w3m.el'.
+(defvar w3m-mode-map) ; In `w3m.el'.
+(defvar woman-menu) ; In `woman.el'.
+(defvar woman-mode-map) ; In `woman.el'.
+
+;;(@* "Keymaps")
+;;; Keymaps ----------------------------------------------------------
+
+;; `help-map'
+(define-key help-map "M" 'bmkp-describe-bookmark)
+
+;; `bookmark-map'
+
+;; (define-key ctl-x-map "x" bookmark-map)
+;; (define-key ctl-x-map "xj" 'bookmark-jump-other-window) ; `C-x x j' (also `C-x 4 j j')
+(define-key ctl-x-map "rK" 'bmkp-set-desktop-bookmark) ; `C-x r K' (also `C-x x K', `C-x x c K')
+
+(define-key bookmark-map "0" 'bmkp-empty-file) ; `C-x x 0'
+(define-key bookmark-map "2" 'bmkp-clone-bookmark) ; `C-x x 2'
+(define-key bookmark-map "5" 'bookmark-jump-other-frame) ; `C-x x 5'
+(define-key bookmark-map "B" 'bmkp-choose-navlist-from-bookmark-list) ; `C-x x B'
+;; `e' is `edit-bookmarks' (aka `bookmark-bmenu-list', from vanilla Emacs.
+(define-key bookmark-map "E" 'bmkp-edit-bookmark-record) ; `C-x x E'
+;; The original `bookmark-insert-location' in `bookmark.el' was `f'.
+(define-key bookmark-map "I" 'bookmark-insert-location) ; `C-x x I'
+(define-key bookmark-map "\C-j" 'bmkp-jump-to-list) ; `C-x x C-j'
+(define-key bookmark-map "K" 'bmkp-set-desktop-bookmark) ; `C-x x K' (also `C-x r K', `C-x x c K')
+(define-key bookmark-map "L" 'bmkp-switch-bookmark-file-create) ; `C-x x L'
+(define-key bookmark-map "\C-l" 'bmkp-switch-to-bookmark-file-this-file/buffer) ; `C-x x C-l'
+(define-key bookmark-map "m" 'bmkp-bookmark-set-confirm-overwrite) ; `C-x x m'
+(define-key bookmark-map "N" 'bmkp-navlist-bmenu-list) ; `C-x x N'
+(define-key bookmark-map "o" 'bookmark-jump-other-window) ; `C-x x o' (also `C-x 4 j j')
+(define-key bookmark-map "q" 'bookmark-jump-other-window) ; `C-x x q' (also `C-x 4 j j')
+(define-key bookmark-map "r" 'bmkp-edit-bookmark-name-and-location) ; `C-x x r'
+(define-key bookmark-map "\C-s" 'bmkp-save-bookmarks-this-file/buffer) ; `C-x x C-s'
+(define-key bookmark-map "\M-w" 'bmkp-set-snippet-bookmark) ; `C-x x M-w' (also `C-x x c M-w')
+(define-key bookmark-map "x" 'bmkp-toggle-autotemp-on-set) ; `C-x x x'
+(define-key bookmark-map "y" 'bmkp-set-bookmark-file-bookmark) ; `C-x x y'
+(when (featurep 'bookmark+-lit)
+ (define-key bookmark-map "h" 'bmkp-light-bookmark-this-buffer) ; `C-x x h'
+ (define-key bookmark-map "H" 'bmkp-light-bookmarks) ; `C-x x H'
+ (define-key bookmark-map "u" 'bmkp-unlight-bookmark-this-buffer) ; `C-x x u'
+ (define-key bookmark-map "U" 'bmkp-unlight-bookmarks) ; `C-x x U'
+ (define-key bookmark-map "\C-u" 'bmkp-unlight-bookmark-here) ; `C-x x C-u'
+ (define-key bookmark-map "=" 'bmkp-bookmarks-lighted-at-point)) ; `C-x x ='
+(define-key bookmark-map "," 'bmkp-this-file/buffer-bmenu-list) ; `C-x x ,'
+(define-key bookmark-map "?" 'bmkp-describe-bookmark-lighted-here) ; `C-x x ?'
+(define-key bookmark-map ":" 'bmkp-choose-navlist-of-type) ; `C-x x :'
+(define-key bookmark-map "\r" 'bmkp-toggle-autonamed-bookmark-set/delete) ; `C-x x RET'
+(define-key bookmark-map [delete] 'bmkp-delete-bookmarks) ; `C-x x delete'
+
+(substitute-key-definition 'kill-line 'bmkp-delete-bookmarks ; `C-x x C-k', `C-x x deleteline'
+ bookmark-map (current-global-map))
+(define-key bookmark-map [deletechar] 'bmkp-delete-bookmarks) ; `C-x x deletechar'
+;; For Mac Book:
+(define-key bookmark-map [kp-delete] 'bmkp-delete-bookmarks) ; `C-x x kp-delete'
+
+;; If you use Emacs before Emacs 22, then you will want to bind the commands
+;; whose names do *not* end in `-repeat' to keys that are easily repeatable.
+;; For example, you might want to bind `bmkp-next-bookmark-this-file/buffer'
+;; (not `bmkp-next-bookmark-this-file/buffer-repeat') to a key such as [f2].
+;;
+(when (> emacs-major-version 21)
+ (define-key bookmark-map "n" 'bmkp-next-bookmark-this-file/buffer-repeat) ; `C-x x n'
+ (define-key bookmark-map "\C-n" 'bmkp-next-bookmark-this-file/buffer-repeat) ; `C-x x C-n'
+ (define-key bookmark-map [down] 'bmkp-next-bookmark-this-file/buffer-repeat) ; `C-x x down'
+ (put 'bmkp-next-bookmark-this-file/buffer-repeat :advertised-binding (kbd "C-x x <down>"))
+
+ ;; This requires the fix for Emacs bug #6256, which is in Emacs 23.3 (presumably).
+ ;; For older Emacs versions you can bind the wheel event to `bmkp-next-bookmark-this-file/buffer'
+ ;; in the global map. IOW, prior to Emacs 23.3 a mouse event won't work with `repeat'.
+ (when (and (boundp 'mouse-wheel-up-event)
+ (or (> emacs-major-version 23)
+ (and (= emacs-major-version 23) (> emacs-minor-version 2))))
+ (define-key bookmark-map (vector (list mouse-wheel-up-event))
+ 'bmkp-next-bookmark-this-file/buffer-repeat)) ; `C-x x mouse-wheel-up'
+ (define-key bookmark-map "p" 'bmkp-previous-bookmark-this-file/buffer-repeat) ; `C-x x p'
+ (define-key bookmark-map "\C-p" 'bmkp-previous-bookmark-this-file/buffer-repeat) ; `C-x x C-p'
+ (define-key bookmark-map [up] 'bmkp-previous-bookmark-this-file/buffer-repeat) ; `C-x x up'
+ (put 'bmkp-previous-bookmark-this-file/buffer-repeat :advertised-binding (kbd "C-x x <up>"))
+
+ ;; This requires the fix for Emacs bug #6256, which is in Emacs 23.3 (presumably).
+ ;; For older Emacs versions you can bind the wheel event to `bmkp-previous-bookmark-this-file/buffer'
+ ;; in the global map. IOW, prior to Emacs 23.3 a mouse event won't work with `repeat'.
+ (when (and (boundp 'mouse-wheel-down-event)
+ (or (> emacs-major-version 23)
+ (and (= emacs-major-version 23) (> emacs-minor-version 2))))
+ (define-key bookmark-map (vector (list mouse-wheel-down-event))
+ 'bmkp-previous-bookmark-this-file/buffer-repeat)) ; `C-x x mouse-wheel-down'
+ (define-key bookmark-map "f" 'bmkp-next-bookmark-repeat) ; `C-x x f'
+ (define-key bookmark-map "\C-f" 'bmkp-next-bookmark-repeat) ; `C-x x C-f'
+ (define-key bookmark-map [right] 'bmkp-next-bookmark-repeat) ; `C-x x right'
+ (put 'bmkp-next-bookmark-repeat :advertised-binding (kbd "C-x x <right>"))
+ (define-key bookmark-map "b" 'bmkp-previous-bookmark-repeat) ; `C-x x b'
+ (define-key bookmark-map "\C-b" 'bmkp-previous-bookmark-repeat) ; `C-x x C-b'
+ (define-key bookmark-map [left] 'bmkp-previous-bookmark-repeat) ; `C-x x left'
+ (put 'bmkp-previous-bookmark-repeat :advertised-binding (kbd "C-x x <left>"))
+ (define-key bookmark-map [next] 'bmkp-next-bookmark-w32-repeat) ; `C-x x next'
+ (define-key bookmark-map [prior] 'bmkp-previous-bookmark-w32-repeat) ; `C-x x prior'
+ (when (featurep 'bookmark+-lit)
+ (define-key bookmark-map [C-down] 'bmkp-next-lighted-this-buffer-repeat) ; `C-x x C-down'
+ (define-key bookmark-map [C-up] 'bmkp-previous-lighted-this-buffer-repeat))) ; `C-x x C-up'
+
+
+;; `bmkp-annotate-map': prefix `C-x x a'
+
+(defvar bmkp-annotate-map nil "Keymap containing bindings for bookmark annotation commands.")
+
+(define-prefix-command 'bmkp-annotate-map)
+(define-key bookmark-map "a" bmkp-annotate-map) ; `C-x x a' for annotate
+
+(define-key bmkp-annotate-map "a" 'bmkp-annotate-bookmark) ; `C-x x a a'
+(define-key bmkp-annotate-map "b" 'bmkp-annotate-bookmark-this-file/buffer) ; `C-x x a b'
+(define-key bmkp-annotate-map "B" 'bmkp-annotate-all-bookmarks-this-file/buffer) ; `C-x x a B'
+(define-key bmkp-annotate-map "e" 'bookmark-edit-annotation) ; `C-x x a e'
+(define-key bmkp-annotate-map "s" 'bookmark-show-annotation) ; `C-x x a s'
+(define-key bmkp-annotate-map "S" 'bookmark-show-all-annotations) ; `C-x x a S'
+
+
+;; `bmkp-set-map': prefix `C-x x c'
+
+(defvar bmkp-set-map nil "Keymap containing bindings for bookmark set commands.")
+
+(define-prefix-command 'bmkp-set-map)
+(define-key bookmark-map "c" bmkp-set-map) ; `C-x x c' for create
+
+(define-key bmkp-set-map "a" 'bmkp-autofile-set) ; `C-x x c a'
+(define-key bmkp-set-map "f" 'bmkp-file-target-set) ; `C-x x c f'
+(define-key bmkp-set-map "F" 'bmkp-make-function-bookmark) ; `C-x x c F'
+(define-key bmkp-set-map "K" 'bmkp-set-desktop-bookmark) ; `C-x x c K'
+(define-key bmkp-set-map "\C-k" 'bmkp-wrap-bookmark-with-last-kbd-macro) ; `C-x x C-k'
+(define-key bmkp-set-map "m" 'bmkp-bookmark-set-confirm-overwrite) ; `C-x x c m'
+(define-key bmkp-set-map "M" 'bookmark-set) ; `C-x x c M'
+(define-key bmkp-set-map "s" 'bmkp-set-sequence-bookmark) ; `C-x x c s'
+(define-key bmkp-set-map "u" 'bmkp-url-target-set) ; `C-x x c u'
+(define-key bmkp-set-map "\M-w" 'bmkp-set-snippet-bookmark) ; `C-x x c M-w'
+(define-key bmkp-set-map "y" 'bmkp-set-bookmark-file-bookmark) ; `C-x x c y'
+(define-key bmkp-set-map "\r" 'bmkp-toggle-autonamed-bookmark-set/delete) ; `C-x x c RET'
+
+
+;; Add set commands to other keymaps: occur, compilation: `C-c C-b', `C-c C-M-b', `C-c C-M-B'.
+;; See `dired+.el' for Dired bookmarking keys, which are different.
+
+(add-hook 'occur-mode-hook
+ (lambda ()
+ (unless (lookup-key occur-mode-map "\C-c\C-b")
+ (define-key occur-mode-map "\C-c\C-b" 'bmkp-occur-target-set)) ; `C-c C-b'
+ (unless (lookup-key occur-mode-map "\C-c\C-\M-b")
+ (define-key occur-mode-map "\C-c\C-\M-b" 'bmkp-occur-target-set-all)) ; `C-c C-M-b'
+ (unless (lookup-key occur-mode-map [(control ?c) (control meta shift ?b)])
+ (define-key occur-mode-map [(control ?c) (control meta shift ?b)]
+ 'bmkp-occur-create-autonamed-bookmarks)))) ; `C-c C-M-B' (aka `C-c C-M-S-b')
+
+(when (fboundp 'bmkp-compilation-target-set) ; Emacs 22+
+
+ (add-hook 'compilation-mode-hook
+ (lambda ()
+ (unless (lookup-key compilation-mode-map "\C-c\C-b")
+ (define-key compilation-mode-map "\C-c\C-b" 'bmkp-compilation-target-set)) ; `C-c C-b'
+ (unless (lookup-key compilation-mode-map "\C-c\C-\M-b") ; `C-c C-M-b'
+ (define-key compilation-mode-map "\C-c\C-\M-b" 'bmkp-compilation-target-set-all))))
+
+ (when (fboundp 'compilation-minor-mode) ; Emacs 26+
+
+ (add-hook
+ 'grep-mode-hook
+ (lambda ()
+ (unless (lookup-key grep-mode-map "\C-c\C-b")
+ (define-key grep-mode-map "\C-c\C-b" 'bmkp-compilation-target-set)) ; `C-c C-b'
+ (unless (lookup-key grep-mode-map "\C-c\C-\M-b") ; `C-c C-M-b'
+ (define-key grep-mode-map "\C-c\C-\M-b" 'bmkp-compilation-target-set-all))))
+
+ (add-hook
+ 'compilation-minor-mode-hook
+ (lambda ()
+ (unless (lookup-key compilation-minor-mode-map "\C-c\C-b")
+ (define-key compilation-minor-mode-map "\C-c\C-b" 'bmkp-compilation-target-set)) ; `C-c C-b'
+ (unless (lookup-key compilation-minor-mode-map "\C-c\C-\M-b") ; `C-c C-M-b'
+ (define-key compilation-minor-mode-map "\C-c\C-\M-b" 'bmkp-compilation-target-set-all))))
+
+ (add-hook
+ 'compilation-shell-minor-mode-hook
+ (lambda ()
+ (unless (lookup-key compilation-shell-minor-mode-map "\C-c\C-b")
+ (define-key compilation-shell-minor-mode-map
+ "\C-c\C-b" 'bmkp-compilation-target-set)) ; `C-c C-b'
+ (unless (lookup-key compilation-shell-minor-mode-map "\C-c\C-\M-b") ; `C-c C-M-b'
+ (define-key compilation-shell-minor-mode-map
+ "\C-c\C-\M-b" 'bmkp-compilation-target-set-all))))))
+
+
+;; `bmkp-tags-map': prefix `C-x x t'
+
+(defvar bmkp-tags-map nil "Keymap containing bindings for bookmark tag commands.")
+
+(define-prefix-command 'bmkp-tags-map)
+(define-key bookmark-map "t" bmkp-tags-map) ; `C-x x t' for tags
+
+(define-key bmkp-tags-map "0" 'bmkp-remove-all-tags) ; `C-x x t 0'
+(define-key bmkp-tags-map "+" nil) ; For Emacs 20
+(define-key bmkp-tags-map "+b" 'bmkp-add-tags) ; `C-x x t + b'
+(define-key bmkp-tags-map "-b" 'bmkp-remove-tags) ; `C-x x t - b'
+(define-key bmkp-tags-map "+a" 'bmkp-tag-a-file) ; `C-x x t + a'
+(define-key bmkp-tags-map "-a" 'bmkp-untag-a-file) ; `C-x x t - a'
+(define-key bmkp-tags-map "c" 'bmkp-copy-tags) ; `C-x x t c'
+(define-key bmkp-tags-map "d" 'bmkp-remove-tags-from-all) ; `C-x x t d'
+(define-key bmkp-tags-map "e" 'bmkp-edit-tags) ; `C-x x t e'
+(define-key bmkp-tags-map "l" 'bmkp-list-all-tags) ; `C-x x t l'
+(define-key bmkp-tags-map "p" 'bmkp-paste-add-tags) ; `C-x x t p'
+(define-key bmkp-tags-map "q" 'bmkp-paste-replace-tags) ; `C-x x t q'
+(define-key bmkp-tags-map "r" 'bmkp-rename-tag) ; `C-x x t r'
+(define-key bmkp-tags-map "v" 'bmkp-set-tag-value) ; `C-x x t v'
+(define-key bmkp-tags-map "V" 'bmkp-set-tag-value-for-navlist) ; `C-x x t V'
+(define-key bmkp-tags-map "\M-w" 'bmkp-copy-tags) ; `C-x x t M-w'
+(define-key bmkp-tags-map "\C-y" 'bmkp-paste-add-tags) ; `C-x x t C-y'
+
+
+;; `bmkp-jump-map' and `bmkp-jump-other-window-map': prefixes `C-x j' and `C-x 4 j'
+
+(defvar bmkp-jump-map nil "Keymap containing bindings for bookmark jump commands.")
+
+(defvar bmkp-jump-other-window-map nil
+ "Keymap containing bindings for bookmark jump other-window commands.")
+
+(define-prefix-command 'bmkp-jump-map)
+(define-prefix-command 'bmkp-jump-other-window-map)
+;; (define-key ctl-x-map "j" bmkp-jump-map)
+;; (define-key ctl-x-4-map "j" bmkp-jump-other-window-map)
+(define-key bookmark-bmenu-mode-map "j" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "J" nil) ; For Emacs 20
+(define-key bookmark-bmenu-mode-map "J" bmkp-jump-map)
+(define-key bookmark-bmenu-mode-map "j" bmkp-jump-other-window-map)
+(define-key bookmark-bmenu-mode-map "j>" 'bmkp-bmenu-jump-to-marked) ; `j >'
+
+(define-key ctl-x-5-map "B" 'bookmark-jump-other-frame) ; `C-x j 5', `C-x 5 B'
+(define-key bmkp-jump-map "5" 'bookmark-jump-other-frame ) ; `J 5'
+(define-key bmkp-jump-map "." nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "." nil) ; For Emacs 20
+(define-key bmkp-jump-map ".d" 'bmkp-dired-this-dir-jump) ; `C-x j . d'
+(define-key bmkp-jump-other-window-map ".d" 'bmkp-dired-this-dir-jump-other-window) ; `C-x 4 j . d'
+(define-key bmkp-jump-map ".f" 'bmkp-file-this-dir-jump) ; `C-x j . f'
+(define-key bmkp-jump-other-window-map ".f" 'bmkp-file-this-dir-jump-other-window) ; `C-x 4 j . f'
+
+(define-key bmkp-jump-map "," nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "," nil) ; For Emacs 20
+(define-key bmkp-jump-map ",," 'bmkp-this-buffer-jump) ; `C-x j , ,'
+(define-key bmkp-jump-other-window-map ",," 'bmkp-this-buffer-jump-other-window) ; `C-x 4 j , ,'
+(define-key bmkp-jump-map ",#" 'bmkp-autonamed-this-buffer-jump) ; `C-x j , #'
+(define-key bmkp-jump-other-window-map ",#"
+ 'bmkp-autonamed-this-buffer-jump-other-window) ; `C-x 4 j , #'
+
+(define-key bmkp-jump-map "#" 'bmkp-autonamed-jump) ; `C-x j #'
+(define-key bmkp-jump-other-window-map "#" 'bmkp-autonamed-jump-other-window) ; `C-x 4 j #'
+
+(define-key bmkp-jump-map "=" nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "=" nil) ; For Emacs 20
+(define-key bmkp-jump-map "=b" 'bmkp-specific-buffers-jump) ; `C-x j = b'
+(define-key bmkp-jump-other-window-map "=b" 'bmkp-specific-buffers-jump-other-window) ; `C-x 4 j = b'
+(define-key bmkp-jump-map "=f" 'bmkp-specific-files-jump) ; `C-x j = f'
+(define-key bmkp-jump-other-window-map "=f" 'bmkp-specific-files-jump-other-window) ; `C-x 4 j = f'
+
+(define-key bmkp-jump-map "a" 'bmkp-autofile-jump) ; `C-x j a'
+(define-key bmkp-jump-other-window-map "a" 'bmkp-autofile-jump-other-window) ; `C-x 4 j a'
+(define-key bmkp-jump-map "b" 'bmkp-non-file-jump) ; `C-x j b'
+(define-key bmkp-jump-other-window-map "b" 'bmkp-non-file-jump-other-window) ; `C-x 4 j b'
+(define-key bmkp-jump-map "B" 'bmkp-bookmark-list-jump) ; `C-x j B'
+(define-key bmkp-jump-other-window-map "B" 'bmkp-bookmark-list-jump) ; SAME COMMAND: `C-x 4 j B'
+(define-key bmkp-jump-map "d" 'bmkp-dired-jump) ; `C-x j d'
+(define-key bmkp-jump-other-window-map "d" 'bmkp-dired-jump-other-window) ; `C-x 4 j d'
+
+(eval-after-load "eww"
+ '(when (> emacs-major-version 24) ; Emacs 25+
+ (when bmkp-eww-replace-keys-flag
+ (bmkp-remap 'eww-add-bookmark 'bookmark-set eww-mode-map)
+ (bmkp-remap 'eww-list-bookmarks 'bookmark-bmenu-list eww-mode-map)
+ (bmkp-remap 'eww-next-bookmark 'bmkp-next-url-bookmark eww-mode-map)
+ (bmkp-remap 'eww-previous-bookmark 'bmkp-previous-url-bookmark eww-mode-map))
+ (define-key bmkp-jump-map "e" 'bmkp-eww-jump) ; `C-x j e'
+ (define-key bmkp-jump-other-window-map "e" 'bmkp-eww-jump-other-window))) ; `C-x 4 j e'
+
+(define-key bmkp-jump-map "f" 'bmkp-file-jump) ; `C-x j f'
+(define-key bmkp-jump-other-window-map "f" 'bmkp-file-jump-other-window) ; `C-x 4 j f'
+(define-key bmkp-jump-map "\C-f" 'bmkp-find-file) ; `C-x j C-f'
+(define-key bmkp-jump-other-window-map "\C-f" 'bmkp-find-file-other-window) ; `C-x 4 j C-f'
+(define-key bmkp-jump-map "g" 'bmkp-gnus-jump) ; `C-x j g'
+(define-key bmkp-jump-other-window-map "g" 'bmkp-gnus-jump-other-window) ; `C-x 4 j g'
+(define-key bmkp-jump-map "h" 'bmkp-lighted-jump) ; `C-x j h'
+(define-key bmkp-jump-other-window-map "h" 'bmkp-lighted-jump-other-window) ; `C-x 4 j h'
+(define-key bmkp-jump-map "i" 'bmkp-info-jump) ; `C-x j i'
+(define-key bmkp-jump-other-window-map "i" 'bmkp-info-jump-other-window) ; `C-x 4 j i'
+(define-key bmkp-jump-map "\M-i" 'bmkp-image-jump) ; `C-x j M-i'
+(define-key bmkp-jump-other-window-map "\M-i" 'bmkp-image-jump-other-window) ; `C-x 4 j M-i'
+(define-key bmkp-jump-map "j" 'bookmark-jump) ; `C-x j j'
+(put 'bookmark-jump :advertised-binding "\C-xjj")
+
+(define-key bmkp-jump-other-window-map "j" 'bookmark-jump-other-window) ; `C-x 4 j j'
+(put 'bookmark-jump-other-window :advertised-binding "\C-x4jj")
+(put 'jump-other :advertised-binding "\C-x4jj")
+
+(define-key bmkp-jump-map "\C-j" 'bmkp-jump-to-list) ; `C-x j C-j'
+(define-key bmkp-jump-map "K" 'bmkp-desktop-jump) ; `C-x j K'
+(define-key bmkp-jump-other-window-map "K" 'bmkp-desktop-jump) ; SAME COMMAND: `C-x 4 j K'
+(define-key bmkp-jump-map "l" 'bmkp-local-file-jump) ; `C-x j l'
+(define-key bmkp-jump-other-window-map "l" 'bmkp-local-file-jump-other-window) ; `C-x 4 j l'
+(define-key bmkp-jump-map "m" 'bmkp-man-jump) ; `C-x j m'
+(define-key bmkp-jump-other-window-map "m" 'bmkp-man-jump-other-window) ; `C-x 4 j m'
+(define-key bmkp-jump-map "n" 'bmkp-remote-file-jump) ; `C-x j n' ("_n_etwork")
+(define-key bmkp-jump-other-window-map "n" 'bmkp-remote-file-jump-other-window) ; `C-x 4 j n'
+(define-key bmkp-jump-map "N" 'bmkp-jump-in-navlist) ; `C-x j N'
+(define-key bmkp-jump-other-window-map "N" 'bmkp-jump-in-navlist-other-window) ; `C-x 4 j N'
+(define-key bmkp-jump-map "r" 'bmkp-region-jump) ; `C-x j r'
+(define-key bmkp-jump-other-window-map "r" 'bmkp-region-jump-other-window) ; `C-x 4 j r'
+(define-key bmkp-jump-other-window-map "R"
+ 'bmkp-region-jump-narrow-indirect-other-window) ; `C-x 4 j R'
+
+(define-key bmkp-jump-map "t" nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "t" nil) ; For Emacs 20
+(define-key bmkp-jump-map "t*" 'bmkp-all-tags-jump) ; `C-x j t *'
+(define-key bmkp-jump-other-window-map "t*" 'bmkp-all-tags-jump-other-window) ; `C-x 4 j t *'
+(define-key bmkp-jump-map "t+" 'bmkp-some-tags-jump) ; `C-x j t +'
+(define-key bmkp-jump-other-window-map "t+" 'bmkp-some-tags-jump-other-window) ; `C-x 4 j t +'
+
+(define-key bmkp-jump-map "t%" nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "t%" nil) ; For Emacs 20
+(define-key bmkp-jump-map "t%*" 'bmkp-all-tags-regexp-jump) ; `C-x j t % *'
+(define-key bmkp-jump-other-window-map "t%*"
+ 'bmkp-all-tags-regexp-jump-other-window) ; `C-x 4 j t % *'
+(define-key bmkp-jump-map "t%+" 'bmkp-some-tags-regexp-jump) ; `C-x j t % +'
+(define-key bmkp-jump-other-window-map "t%+"
+ 'bmkp-some-tags-regexp-jump-other-window) ; `C-x 4 j t % +'
+
+(define-key bmkp-jump-map "t." nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "t." nil) ; For Emacs 20
+(define-key bmkp-jump-map "t.*" 'bmkp-file-this-dir-all-tags-jump) ; `C-x j t . *'
+(define-key bmkp-jump-other-window-map "t.*"
+ 'bmkp-file-this-dir-all-tags-jump-other-window) ; `C-x 4 j t . *'
+(define-key bmkp-jump-map "t.+" 'bmkp-file-this-dir-some-tags-jump) ; `C-x j t . +'
+(define-key bmkp-jump-other-window-map "t.+"
+ 'bmkp-file-this-dir-some-tags-jump-other-window) ; `C-x 4 j t . +'
+
+(define-key bmkp-jump-map "t.%" nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "t.%" nil) ; For Emacs 20
+(define-key bmkp-jump-map "t.%*"
+ 'bmkp-file-this-dir-all-tags-regexp-jump) ; `C-x j t . % *'
+(define-key bmkp-jump-other-window-map "t.%*"
+ 'bmkp-file-this-dir-all-tags-regexp-jump-other-window) ; `C-x 4 j t . % *'
+(define-key bmkp-jump-map "t.%+"
+ 'bmkp-file-this-dir-some-tags-regexp-jump) ; `C-x j t . % +'
+(define-key bmkp-jump-other-window-map "t.%+"
+ 'bmkp-file-this-dir-some-tags-regexp-jump-other-window) ; `C-x 4 j t . % +'
+
+
+(define-key bmkp-jump-map "ta" nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "ta" nil) ; For Emacs 20
+(define-key bmkp-jump-map "ta*" 'bmkp-autofile-all-tags-jump) ; `C-x j t a *'
+(define-key bmkp-jump-other-window-map "ta*"
+ 'bmkp-autofile-all-tags-jump-other-window) ; `C-x 4 j t a *'
+(define-key bmkp-jump-map "ta+" 'bmkp-autofile-some-tags-jump) ; `C-x j t a +'
+(define-key bmkp-jump-other-window-map "ta+"
+ 'bmkp-autofile-some-tags-jump-other-window) ; `C-x 4 j t a +'
+
+(define-key bmkp-jump-map "ta%" nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "ta%" nil) ; For Emacs 20
+(define-key bmkp-jump-map "ta%*" 'bmkp-autofile-all-tags-regexp-jump) ; `C-x j t a % *'
+(define-key bmkp-jump-other-window-map "ta%*"
+ 'bmkp-autofile-all-tags-regexp-jump-other-window) ; `C-x 4 j t a % *'
+(define-key bmkp-jump-map "ta%+" 'bmkp-autofile-some-tags-regexp-jump) ; `C-x j t a % +'
+(define-key bmkp-jump-other-window-map "ta%+"
+ 'bmkp-autofile-some-tags-regexp-jump-other-window) ; `C-x 4 j t a % +'
+
+(define-key bmkp-jump-map "tf" nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "tf" nil) ; For Emacs 20
+(define-key bmkp-jump-map "tf*" 'bmkp-file-all-tags-jump) ; `C-x j t f *'
+(define-key bmkp-jump-other-window-map "tf*" 'bmkp-file-all-tags-jump-other-window) ; `C-x 4 j t f *'
+(define-key bmkp-jump-map "tf+" 'bmkp-file-some-tags-jump) ; `C-x j t f +'
+(define-key bmkp-jump-other-window-map "tf+" 'bmkp-file-some-tags-jump-other-window) ; `C-x 4 j t f +'
+
+(define-key bmkp-jump-map "tf%" nil) ; For Emacs 20
+(define-key bmkp-jump-other-window-map "tf%" nil) ; For Emacs 20
+(define-key bmkp-jump-map "tf%*" 'bmkp-file-all-tags-regexp-jump) ; `C-x j t f % *'
+(define-key bmkp-jump-other-window-map "tf%*"
+ 'bmkp-file-all-tags-regexp-jump-other-window) ; `C-x 4 j t f % *'
+(define-key bmkp-jump-map "tf%+" 'bmkp-file-some-tags-regexp-jump) ; `C-x j t f % +'
+(define-key bmkp-jump-other-window-map "tf%+"
+ 'bmkp-file-some-tags-regexp-jump-other-window) ; `C-x 4 j t f % +'
+
+(when (> emacs-major-version 21) ; Needs `read-file-name' with a PREDICATE arg.
+ (define-key bmkp-jump-map "t\C-f*" 'bmkp-find-file-all-tags) ; `C-x j t C-f *'
+ (define-key bmkp-jump-other-window-map "t\C-f*"
+ 'bmkp-find-file-all-tags-other-window) ; `C-x 4 j t C-f *'
+ (define-key bmkp-jump-map "t\C-f+" 'bmkp-find-file-some-tags) ; `C-x j t C-f +'
+ (define-key bmkp-jump-other-window-map "t\C-f+"
+ 'bmkp-find-file-some-tags-other-window) ; `C-x 4 j t C-f +'
+ (define-key bmkp-jump-map "t\C-f%*" 'bmkp-find-file-all-tags-regexp) ; `C-x j t C-f % *'
+ (define-key bmkp-jump-other-window-map "t\C-f%*"
+ 'bmkp-find-file-all-tags-regexp-other-window) ; `C-x 4 j t C-f % *'
+ (define-key bmkp-jump-map "t\C-f%+"
+ 'bmkp-find-file-some-tags-regexp) ; `C-x j t C-f % +'
+ (define-key bmkp-jump-other-window-map "t\C-f%+"
+ 'bmkp-find-file-some-tags-regexp-other-window)) ; `C-x 4 j t C-f % +'
+
+(define-key bmkp-jump-map "u" 'bmkp-url-jump) ; `C-x j u'
+(define-key bmkp-jump-other-window-map "u" 'bmkp-url-jump-other-window) ; `C-x 4 j u'
+(define-key bmkp-jump-map "v" 'bmkp-variable-list-jump) ; `C-x j v'
+(define-key bmkp-jump-map "w" 'bmkp-w3m-jump) ; `C-x j w'
+(define-key bmkp-jump-other-window-map "w" 'bmkp-w3m-jump-other-window) ; `C-x 4 j w'
+(define-key bmkp-jump-map "\M-w" 'bmkp-snippet-to-kill-ring) ; `C-x j M-w'
+(define-key bmkp-jump-other-window-map "\M-w" 'bmkp-snippet-to-kill-ring) ; SAME CMD: `C-x 4 j M-w'
+(define-key bmkp-jump-map "x" 'bmkp-temporary-jump) ; `C-x j x'
+(define-key bmkp-jump-other-window-map "x" 'bmkp-temporary-jump-other-window) ; `C-x 4 j x'
+(define-key bmkp-jump-map "y" 'bmkp-bookmark-file-jump) ; `C-x j y'
+(define-key bmkp-jump-map ":" 'bmkp-jump-to-type) ; `C-x j :'
+(define-key bmkp-jump-other-window-map ":" 'bmkp-jump-to-type-other-window) ; `C-x 4 j :'
+
+(defun bmkp-exists-bookmark-satisfying-p (predicate &optional alist)
+ "Return t if there is a bookmark in ALIST that satisfies PREDICATE.
+Else return nil. ALIST defaults to `bookmark-alist'.
+Put differently, return t iff the filtered alist is non-empty."
+ (catch 'bmkp-exists-bookmark-satisfying-p
+ (dolist (bmk (or alist bookmark-alist))
+ (when (funcall predicate bmk) (throw 'bmkp-exists-bookmark-satisfying-p t)))
+ nil))
+
+(defun bmkp-exists-this-file/buffer-bookmarks-p (&optional alist)
+ "Return t if there is a this-file or this-buffer bookmark in ALIST."
+ (bmkp-exists-bookmark-satisfying-p (if (buffer-file-name) #'bmkp-this-file-p #'bmkp-this-buffer-p)))
+
+(defvar bmkp-bookmarks-here-menu-command-entries
+ (list (list 'bmkp-next-bookmark-this-file/buffer-repeat
+ 'menu-item
+ "Next Bookmark Here"
+ 'bmkp-next-bookmark-this-file/buffer-repeat
+ :help "Jump to the next bookmark in this buffer")
+ (list 'bmkp-previous-bookmark-this-file/buffer-repeat
+ 'menu-item
+ "Previous Bookmark Here"
+ 'bmkp-previous-bookmark-this-file/buffer-repeat
+ :help "Jump to the previous bookmark in this buffer")
+ (list 'bmkp-here-sep1 'menu-item "--")
+ (list 'bmkp-annotate-bookmark-this-file/buffer
+ 'menu-item
+ "Annotate a Bookmark Here"
+ 'bmkp-annotate-bookmark-this-file/buffer
+ :help "Annotate a bookmark in this buffer")
+ (list 'bmkp-annotate-all-bookmarks-this-file/buffer
+ 'menu-item
+ "Annotate All Bookmarks Here"
+ 'bmkp-annotate-all-bookmarks-this-file/buffer
+ :help "Annotate each bookmark in this buffer")
+ (list 'bmkp-edit-bookmark-record-file/buffer
+ 'menu-item
+ "Edit a Bookmark Record Here"
+ 'bmkp-edit-bookmark-record-file/buffer
+ :help "Edit the full record (Lisp) of a bookmark in this buffer")
+ (list 'bmkp-here-sep2 'menu-item "--")
+ (list 'bmkp-describe-bookmark-lighted-here
+ 'menu-item
+ "Describe Highlighted Bookmark This Line (`C-u': internal form)"
+ 'bmkp-describe-bookmark-lighted-here
+ :help "Describe a highlighted bookmark on this line. `C-u': internal description"
+ :enable '(and (fboundp 'bmkp-describe-bookmark-lighted-here)
+ (or (bmkp-a-bookmark-lighted-at-pos (point) 'FULL)
+ (bmkp-a-bookmark-lighted-on-this-line 'FULL))))
+ (list 'bmkp-bookmarks-lighted-at-point
+ 'menu-item
+ "List Highlighted Bookmarks at Point"
+ 'bmkp-bookmarks-lighted-at-point
+ :help "List the bookmarks at point that are highlighted"
+ :enable '(bmkp-bookmarks-lighted-at-point))
+ (list 'bmkp-set-lighting-for-this-buffer
+ 'menu-item
+ "Set Highlighting for All Bookmarks Here"
+ 'bmkp-set-lighting-for-this-buffer
+ :help "Set the `lighting' entry for all of the bookmarks for this buffer"
+ :visible (featurep 'bookmark+-lit))
+ (list 'bmkp-light-this-buffer
+ 'menu-item
+ "Highlight All Bookmarks Here"
+ 'bmkp-light-this-buffer
+ :help "Highlight the bookmarks in this buffer"
+ :keys "(C-x x H)" ; Really bound to `bmkp-light-bookmarks'
+ :visible (featurep 'bookmark+-lit))
+ (list 'bmkp-unlight-this-buffer
+ 'menu-item
+ "Unhighlight All Bookmarks Here"
+ 'bmkp-unlight-this-buffer
+ :help "Highlight the bookmarks in this buffer"
+ :keys "(C-x x U)" ; Really bound to `bmkp-unlight-bookmarks'
+ :visible (featurep 'bookmark+-lit))
+ (list 'bmkp-light-autonamed-this-buffer
+ 'menu-item
+ "Highlight Autonamed Bookmarks Here"
+ 'bmkp-light-autonamed-this-buffer
+ :help "Highlight the autonamed bookmarks in this buffer"
+ :visible (featurep 'bookmark+-lit))
+ (list 'bmkp-unlight-autonamed-this-buffer
+ 'menu-item
+ "Unhighlight Autonamed Bookmarks Here"
+ 'bmkp-unlight-autonamed-this-buffer
+ :help "Unhighlight the autonamed bookmarks in this buffer"
+ :visible (featurep 'bookmark+-lit))
+ (list 'bmkp-light-non-autonamed-this-buffer
+ 'menu-item
+ "Highlight Non-Autonamed Bookmarks Here"
+ 'bmkp-light-non-autonamed-this-buffer
+ :help "Highlight the non-autonamed bookmarks in this buffer"
+ :visible (featurep 'bookmark+-lit))
+ (list 'bmkp-unlight-non-autonamed-this-buffer
+ 'menu-item
+ "Unhighlight Non-Autonamed Bookmarks Here"
+ 'bmkp-unlight-non-autonamed-this-buffer
+ :help "Unhighlight the non-autonamed bookmarks in this buffer"
+ :visible (featurep 'bookmark+-lit))
+ (list 'bmkp-here-sep3 'menu-item "--")
+ (list 'bmkp-this-file/buffer-bmenu-list
+ 'menu-item
+ "Show Bookmark List for Bookmarks Here"
+ 'bmkp-this-file/buffer-bmenu-list
+ :help "Show the bookmark list for bookmarks in this buffer")
+ (list 'bmkp-switch-to-bookmark-file-this-file/buffer
+ 'menu-item
+ "Switch to Bookmark File for Bookmarks Here..."
+ 'bmkp-switch-to-bookmark-file-this-file/buffer
+ :help "Switch to a bookmark file for bookmarks in this buffer")
+ (list 'bmkp-save-bookmarks-this-file/buffer
+ 'menu-item
+ "Save Bookmarks Here To Bookmark File..."
+ 'bmkp-save-bookmarks-this-file/buffer
+ :help "Save all bookmarks defined for this file/buffer to a file"))
+ "Menu entries for general commands in `Bookmarks' > `Here' menu.")
+
+(progn
+ (defvar bmkp-here-menu (make-sparse-keymap)
+ "`Here' submenu for menu-bar `Bookmarks' menu.
+Menu for bookmarks that target this file or buffer.")
+ (define-prefix-command 'bmkp-here-menu)
+ (setcdr bmkp-here-menu bmkp-bookmarks-here-menu-command-entries))
+
+;; Add commands to other keymaps: Buffer-menu, Dired, EWW, Gnus, Info, Man, Woman, W3M.
+
+(add-hook (if (boundp 'Buffer-menu-mode-hook) 'Buffer-menu-mode-hook 'buffer-menu-mode-hook)
+ (lambda ()
+ (unless (lookup-key Buffer-menu-mode-map "j")
+ (define-key Buffer-menu-mode-map "j" 'bmkp-non-file-jump)) ; `j'
+ (define-key Buffer-menu-mode-map [menu-bar Buffer-menu-mode here]
+ `(menu-item "Bookmarks Here" bmkp-here-menu
+ :enable (and bmkp-add-bookmarks-here-menu-flag
+ (bmkp-exists-this-file/buffer-bookmarks-p))))))
+
+(add-hook 'dired-mode-hook
+ (lambda ()
+ (let ((now (lookup-key dired-mode-map "J")))
+ ;; Uppercase, since `j' is `dired-goto-file'.
+ (unless (and now (not (eq now 'undefined))) ; `dired+.el' uses `undefined'.
+ (define-key dired-mode-map "J" 'bmkp-dired-jump)) ; `j'
+ (setq now (lookup-key dired-mode-map "\C-j"))
+ (unless (and now (not (eq now 'undefined))) ; `dired+.el' uses `undefined'.
+ (define-key dired-mode-map "\C-j" 'bmkp-dired-this-dir-jump))) ; `C-j'
+ (let ((map dired-mode-map)
+ (sep '(menu-bar subdir separator-bmkp))
+ (bdj '(menu-bar subdir bmkp-dired-jump))
+ (bdjc '(menu-bar subdir bmkp-dired-this-dir-jump)))
+ (cond ((boundp 'diredp-bookmark-menu) ; In `dired+el'.
+ (setq map diredp-bookmark-menu
+ sep (cddr sep)
+ bdj (cddr bdj)
+ bdjc (cddr bdjc))
+ (define-key map (apply #'vector bdjc)
+ '(menu-item "Jump to a Dired Bookmark For This Dir" bmkp-dired-this-dir-jump
+ :help "Jump to a bookmarked Dired buffer for this directory"))
+ (define-key map (apply #'vector bdj)
+ '(menu-item "Jump to a Dired Bookmark" bmkp-dired-jump
+ :help "Jump to a bookmarked Dired buffer"))
+ (define-key map [bookmarks-here]
+ `(menu-item "Here" bmkp-here-menu
+ :enable (and bmkp-add-bookmarks-here-menu-flag
+ (bmkp-exists-this-file/buffer-bookmarks-p)))))
+ (t
+ (define-key map (apply #'vector sep) '("--")) ;------------------------
+ (define-key map (apply #'vector bdjc)
+ '(menu-item "Jump to a Dired Bookmark For This Dir" bmkp-dired-this-dir-jump
+ :help "Jump to a bookmarked Dired buffer for this directory"))
+ (define-key map (apply #'vector bdj)
+ '(menu-item "Jump to a Dired Bookmark" bmkp-dired-jump
+ :help "Jump to a bookmarked Dired buffer"))
+ (define-key map [bookmarks-here]
+ `(menu-item "Here" bmkp-here-menu
+ :enable (and bmkp-add-bookmarks-here-menu-flag
+ (bmkp-exists-this-file/buffer-bookmarks-p)))))))))
+
+(when (fboundp 'bmkp-eww-jump) ; Emacs 24.4+
+ (add-hook 'eww-mode-hook
+ (lambda () (unless (lookup-key eww-mode-map "j")
+ (define-key eww-mode-map "j" 'bmkp-eww-jump)))))
+
+(add-hook 'gnus-summary-mode-hook
+ (lambda () (unless (lookup-key gnus-summary-mode-map "j")
+ (define-key gnus-summary-mode-map "j" 'bmkp-gnus-jump))))
+
+(add-hook 'Info-mode-hook
+ (lambda ()
+ (unless (lookup-key Info-mode-map "j")
+ (define-key Info-mode-map "j" 'bmkp-info-jump))
+ (define-key-after Info-mode-menu [bmkp-info-jump]
+ '(menu-item "Jump to an Info Bookmark" bmkp-info-jump
+ :help "Jump to a bookmarked Info node")
+ 'Go\ to\ Node\.\.\.) ; Used by `info(+).el' - corresponds to `Info-goto-node'.
+ (define-key Info-mode-menu [bookmarks-here]
+ `(menu-item "Bookmarks Here" bmkp-here-menu
+ :enable (and bmkp-add-bookmarks-here-menu-flag
+ (bmkp-exists-this-file/buffer-bookmarks-p))))))
+
+(add-hook 'Man-mode-hook
+ (lambda () (unless (lookup-key Man-mode-map "j")
+ (define-key Man-mode-map "j" 'bmkp-man-jump))))
+
+(add-hook 'woman-mode-hook
+ (lambda ()
+ (unless (lookup-key woman-mode-map "j") (define-key woman-mode-map "j" 'bmkp-man-jump))
+ (when (boundp 'woman-menu)
+ (define-key-after woman-menu [bmkp-man-jump]
+ '(menu-item "Jump to a `man'-page Bookmark" bmkp-man-jump
+ :help "Jump to a bookmarked `man' page")
+ 'WoMan\.\.\.)))) ; Used by `woman.el' - corresponds to command `woman'.
+
+(add-hook 'w3m-minor-mode-hook
+ (lambda () (unless (lookup-key w3m-minor-mode-map "j")
+ (define-key w3m-minor-mode-map "j" 'bmkp-w3m-jump))))
+
+(add-hook 'w3m-mode-hook
+ (lambda () (unless (lookup-key w3m-mode-map "j")
+ (define-key w3m-mode-map "j" 'bmkp-w3m-jump))))
+
+
+;;; Vanilla Emacs `Bookmarks' menu (see also [jump] from `Bookmark+' menu, below).
+
+(define-key-after menu-bar-bookmark-map [separator-edit] '("--") ;-------------------------------------
+ 'jump)
+;; Remove this predefined item - we use `bmkp-edit-bookmark-name-and-location' instead.
+(define-key menu-bar-bookmark-map [rename] nil)
+
+(define-key-after menu-bar-bookmark-map [bmkp-clone-bookmark]
+ '(menu-item "Clone (Duplicate) a Bookmark" bmkp-clone-bookmark
+ :help "Clone this bookmark. (`\\[bmkp-edit-bookmark-record]' to edit.)")
+ 'separator-edit)
+(define-key-after menu-bar-bookmark-map [bmkp-edit-bookmark-name-and-location]
+ '(menu-item "Rename or Relocate Bookmark..." bmkp-edit-bookmark-name-and-location
+ :help "Rename and/or relocate a bookmark")
+ 'bmkp-clone-bookmark)
+(define-key-after menu-bar-bookmark-map [bmkp-edit-bookmark-record]
+ '(menu-item "Edit Bookmark Record (Lisp)..." bmkp-edit-bookmark-record
+ :help "Edit the internal record of a bookmark,a Lisp sexp")
+ 'bmkp-edit-bookmark-name-and-location)
+
+(define-key-after menu-bar-bookmark-map [separator-show] '("--") ;-------------------------------------
+ 'bmkp-edit-bookmark-record)
+(define-key-after menu-bar-bookmark-map [edit]
+ '(menu-item "Show Bookmark List" bookmark-bmenu-list
+ :help "Open the list of bookmarks in buffer `*Bookmark List*'")
+ 'separator-show)
+(define-key-after menu-bar-bookmark-map [bmkp-this-file/buffer-bmenu-list]
+ '(menu-item "Show Bookmark List for This File/Buffer" bmkp-this-file/buffer-bmenu-list
+ :help "Open `*Bookmark List*' for the bookmarks in the current buffer (only)")
+ 'edit)
+(define-key-after menu-bar-bookmark-map [bmkp-navlist-bmenu-list]
+ '(menu-item "Show Bookmark List for Navlist" bmkp-navlist-bmenu-list
+ :help "Open `*Bookmark List*' for bookmarks in navlist (only)")
+ 'bmkp-this-file/buffer-bmenu-list)
+
+(define-key-after menu-bar-bookmark-map [separator-2] '("--") ;-------------------------------------
+ 'bmkp-navlist-bmenu-list)
+(define-key-after menu-bar-bookmark-map [bmkp-choose-navlist-of-type]
+ '(menu-item "Set Navlist to Bookmarks of Type..." bmkp-choose-navlist-of-type
+ :help "Set the navigation list to the bookmarks of a certain type")
+ 'separator-2)
+(define-key-after menu-bar-bookmark-map [bmkp-choose-navlist-from-bookmark-list]
+ '(menu-item "Set Navlist from Bookmark-List Bookmark..." bmkp-choose-navlist-from-bookmark-list
+ :help "Set the navigation list from a bookmark-list bookmark")
+ 'bmkp-choose-navlist-of-type)
+(define-key-after menu-bar-bookmark-map [bmkp-list-defuns-in-commands-file]
+ '(menu-item "List User-Defined Bookmark Commands" bmkp-list-defuns-in-commands-file
+ :help "List the functions defined in `bmkp-bmenu-commands-file'"
+ :enable (and bmkp-bmenu-commands-file (file-readable-p bmkp-bmenu-commands-file)))
+ 'bmkp-choose-navlist-from-bookmark-list)
+
+(define-key-after menu-bar-bookmark-map [insert]
+ '(menu-item "Insert Bookmark Contents..." bookmark-insert :help "Insert bookmarked text")
+ 'bmkp-choose-navlist-from-bookmark-list)
+(define-key-after menu-bar-bookmark-map [locate]
+ '(menu-item "Insert Bookmark Location..." bookmark-locate ; Alias for `bookmark-insert-location'.
+ :help "Insert a bookmark's file or buffer name")
+ 'insert)
+(when (fboundp 'advice-add) ; Emacs 24.4+.
+ (define-key-after menu-bar-bookmark-map [bmkp-store-org-link]
+ '(menu-item "Store Org Link To..." bmkp-store-org-link
+ :help "Store a link to a bookmark for insertion in an Org-mode buffer")
+ 'locate))
+
+(define-key-after menu-bar-bookmark-map [separator-3] '("--") ;-------------------------------------
+ (if (fboundp 'advice-add) 'bmkp-store-org-link 'locate))
+(define-key-after menu-bar-bookmark-map [save]
+ '(menu-item "Save Bookmarks" bookmark-save :help "Save currently defined bookmarks")
+ 'separator-3)
+(define-key-after menu-bar-bookmark-map [write]
+ '(menu-item "Save Bookmarks As..." bookmark-write
+ :help "Write current bookmarks to a bookmark file")
+ 'save)
+(define-key-after menu-bar-bookmark-map [bmkp-switch-bookmark-file-create]
+ '(menu-item "Switch to Bookmark File..." bmkp-switch-bookmark-file-create
+ :help "Switch to a different bookmark file, *replacing* the current set of bookmarks")
+ 'write)
+(define-key-after menu-bar-bookmark-map [load]
+ '(menu-item "Add Bookmarks from File..." bookmark-load
+ :help "Load additional bookmarks from a bookmark file")
+ 'bmkp-switch-bookmark-file-create)
+(define-key-after menu-bar-bookmark-map [bmkp-empty-file]
+ '(menu-item "Empty Bookmark File..." bmkp-empty-file
+ :help "Empty an existing bookmark file or create a new, empty bookmark file")
+ 'load)
+
+
+;; `bmkp-annotate-menu' of vanilla `Bookmarks' menu: `Annotate'
+
+(defvar bmkp-annotate-menu (make-sparse-keymap)
+ "`Annotate' submenu for menu-bar `Bookmarks' menu.")
+(define-key menu-bar-bookmark-map [annotate] (cons "Annotate" bmkp-annotate-menu))
+
+(define-key bmkp-annotate-menu [bookmark-show-all-annotations]
+ '(menu-item "Show All Annotations" bookmark-show-all-annotations
+ :help "Show the annotations for all bookmarks"))
+(define-key bmkp-annotate-menu [bookmark-show-annotation]
+ '(menu-item "Show an Annotation" bookmark-show-annotation
+ :help "Show the annotation for a bookmark, or follow it if external"))
+(define-key bmkp-annotate-menu [bmkp-annotate-all-bookmarks-this-file/buffer]
+ '(menu-item "Annotate All Bookmarks Here" bmkp-annotate-all-bookmarks-this-file/buffer
+ :help "Pop up an annotation-editing buffer for each bookmark in this buffer"))
+(define-key bmkp-annotate-menu [bmkp-annotate-bookmark-this-file/buffer]
+ '(menu-item "Annotate a Bookmark Here" bmkp-annotate-bookmark-this-file/buffer
+ :help "Annotate an existing bookmark in this buffer"))
+(define-key bmkp-annotate-menu [bmkp-annotate-bookmark]
+ '(menu-item "Annotate a Bookmark" bmkp-annotate-bookmark
+ :help "Pop up a buffer to add or edit an annotation for a bookmark"))
+
+
+;; `bmkp-highlight-menu' of vanilla `Bookmarks' menu: `Highlight'
+
+(when (or (featurep 'bookmark+-lit)
+ (and (fboundp 'diredp-highlight-autofiles-mode) (featurep 'highlight)))
+ (defvar bmkp-highlight-menu (make-sparse-keymap)
+ "`Highlight' submenu for menu-bar `Bookmarks' menu.")
+ (define-key menu-bar-bookmark-map [highlight] (cons "Highlight" bmkp-highlight-menu))
+
+ (when (featurep 'bookmark+-lit)
+ (define-key bmkp-highlight-menu [bmkp-unlight-bookmarks]
+ '(menu-item "Unhighlight All" bmkp-unlight-bookmarks
+ :help "Unhighlight all bookmarks (everywhere)"))
+ (define-key bmkp-highlight-menu [bmkp-unlight-this-buffer]
+ '(menu-item "Unhighlight All in Buffer" bmkp-unlight-this-buffer
+ :help "Unhighlight all bookmarks in this buffer"))
+ (define-key bmkp-highlight-menu [bmkp-unlight-non-autonamed-this-buffer]
+ '(menu-item "Unhighlight All Non-Autonamed in Buffer" bmkp-unlight-non-autonamed-this-buffer
+ :help "Unhighlight all non-autonamed bookmarks in this buffer"))
+ (define-key bmkp-highlight-menu [bmkp-unlight-autonamed-this-buffer]
+ '(menu-item "Unhighlight All Autonamed in Buffer" bmkp-unlight-autonamed-this-buffer
+ :help "Unhighlight all autonamed bookmarks in this buffer"))
+ (define-key bmkp-highlight-menu [bmkp-unlight-bookmark]
+ '(menu-item "Unhighlight One..." bmkp-unlight-bookmark
+ :help "Unhighlight a bookmark"))
+ (define-key bmkp-highlight-menu [bmkp-unlight-bookmark-this-buffer]
+ '(menu-item "Unhighlight One in Buffer..." bmkp-unlight-bookmark-this-buffer
+ :help "Unhighlight a bookmark in this buffer"))
+ (define-key bmkp-highlight-menu [bmkp-unlight-bookmark-here]
+ '(menu-item "Unhighlight This One" bmkp-unlight-bookmark-here
+ :help "Unhighlight a bookmark at point or on its line"))
+
+ (define-key bmkp-highlight-menu [separator-2] '("--")) ;------------------------------------------
+ (define-key bmkp-highlight-menu [bmkp-light-bookmarks-in-region]
+ '(menu-item "Highlight All in Region" bmkp-light-bookmarks-in-region
+ :help "Highlight all bookmarks in the region"))
+ (define-key bmkp-highlight-menu [bmkp-light-this-buffer]
+ '(menu-item "Highlight All in Buffer" bmkp-light-this-buffer
+ :help "Highlight all bookmarks in this buffer"))
+ (define-key bmkp-highlight-menu [bmkp-light-non-autonamed-this-buffer]
+ '(menu-item "Highlight All Non-Autonamed in Buffer" bmkp-light-non-autonamed-this-buffer
+ :help "Highlight all non-autonamed bookmarks in this buffer"))
+ (define-key bmkp-highlight-menu [bmkp-light-autonamed-this-buffer]
+ '(menu-item "Highlight All Autonamed in Buffer" bmkp-light-autonamed-this-buffer
+ :help "Highlight all autonamed bookmarks in this buffer"))
+ (define-key bmkp-highlight-menu [bmkp-light-navlist-bookmarks]
+ '(menu-item "Highlight All in Navigation List" bmkp-light-navlist-bookmarks
+ :help "Highlight all bookmarks in the navigation list"))
+ (define-key bmkp-highlight-menu [bmkp-light-bookmark-this-buffer]
+ '(menu-item "Highlight One in Buffer..." bmkp-light-bookmark-this-buffer
+ :help "Highlight a bookmark in this buffer"))
+ (define-key bmkp-highlight-menu [bmkp-light-bookmark]
+ '(menu-item "Highlight One..." bmkp-light-bookmark
+ :help "Highlight a bookmark"))
+
+ (define-key bmkp-highlight-menu [separator-1] '("--")) ;------------------------------------------
+ (define-key bmkp-highlight-menu [bmkp-describe-bookmark-lighted-here]
+ '(menu-item "Describe Highlighted Here (`C-u': internal form)"
+ bmkp-describe-bookmark-lighted-here
+ :help "Describe a highlighted bookmark on this line."
+ :enable (and (fboundp 'bmkp-describe-bookmark-lighted-here)
+ (or (bmkp-a-bookmark-lighted-at-pos (point) 'FULL)
+ (bmkp-a-bookmark-lighted-on-this-line 'FULL)))))
+ (define-key bmkp-highlight-menu [bmkp-bookmarks-lighted-at-point]
+ '(menu-item "List Highlighted at Point" bmkp-bookmarks-lighted-at-point
+ :help "List the bookmarks at point that are highlighted"
+ :enable (bmkp-bookmarks-lighted-at-point)))
+ (define-key bmkp-highlight-menu [bmkp-next-lighted-this-buffer]
+ '(menu-item "Next in Buffer" bmkp-next-lighted-this-buffer
+ :help "Cycle to the next highlighted bookmark in this buffer"))
+ (define-key bmkp-highlight-menu [bmkp-previous-lighted-this-buffer]
+ '(menu-item "Previous in Buffer" bmkp-previous-lighted-this-buffer
+ :help "Cycle to the previous highlighted bookmark in this buffer"))
+ (define-key bmkp-highlight-menu [separator-0] '("--")) ;------------------------------------------
+ )
+
+ (define-key bmkp-highlight-menu [diredp-highlight-autofiles-mode]
+ (bmkp-menu-bar-make-toggle diredp-highlight-autofiles-mode
+ diredp-highlight-autofiles-mode
+ "Toggle Autofile Highlighting in Dired"
+ "Whether to highlight autofile bookmarks in Dired us biw %s"
+ "Toggle `diredp-highlight-autofiles-mode'"
+ nil
+ :visible (and (fboundp 'diredp-highlight-autofiles-mode)
+ (featurep 'highlight))))
+
+ (when (featurep 'bookmark+-lit)
+ (define-key bmkp-highlight-menu [bmkp-set-lighting-for-bookmark]
+ '(menu-item "Set Highlighting for One..." bmkp-set-lighting-for-bookmark
+ :help "Set individual highlighting for a bookmark"))))
+
+
+;; `bmkp-here-menu' of vanilla `Bookmarks' menu: `Here'
+
+(define-key menu-bar-bookmark-map [bookmarks-here]
+ `(menu-item "Here (This File/Buffer)" bmkp-here-menu
+ :enable (and bmkp-add-bookmarks-here-menu-flag
+ (bmkp-exists-this-file/buffer-bookmarks-p))))
+
+
+;; `bmkp-delete-menu' of vanilla `Bookmarks' menu: `Delete'
+
+(defvar bmkp-delete-menu (make-sparse-keymap)
+ "`Delete' submenu for menu-bar `Bookmarks' menu.")
+(define-key menu-bar-bookmark-map [delete-menu] (cons "Delete" bmkp-delete-menu))
+
+(define-key bmkp-delete-menu [bmkp-delete-all-temporary-bookmarks]
+ '(menu-item "Delete All Temporaries..." bmkp-delete-all-temporary-bookmarks
+ :help "Delete the temporary bookmarks, (`X') whether visible here or not"))
+
+;;; $$$$$$ NOTE: Here and below, the definitions with logically correct `:enable' filters are
+;;; commented out. This is because evaluation of these filters is too slow, especially
+;;; in older Emacs versions. If you want to try some or all of the definitions with the
+;;; `:enable' conditions, just uncomment them and comment out or remove the corresponding
+;;; definitions without such conditions.
+
+;;;;; (define-key bmkp-delete-menu [bmkp-delete-all-autonamed-for-this-buffer]
+;;;;; '(menu-item "Delete All Autonamed Bookmarks Here..."
+;;;;; bmkp-delete-all-autonamed-for-this-buffer
+;;;;; :help "Delete all autonamed bookmarks for the current buffer"
+;;;;; :enable (mapcar #'bmkp-bookmark-name-from-record (bmkp-autonamed-this-buffer-alist-only))))
+(define-key bmkp-delete-menu [bmkp-delete-all-autonamed-for-this-buffer]
+ '(menu-item "Delete All Autonamed Bookmarks Here..."
+ bmkp-delete-all-autonamed-for-this-buffer
+ :help "Delete all autonamed bookmarks for the current buffer"))
+(define-key bmkp-delete-menu [bmkp-toggle-autoname-bookmark-delete]
+ '(menu-item "Delete Autonamed Bookmark" bmkp-toggle-autonamed-bookmark-set/delete
+ :help "Delete the autonamed bookmark at point"
+ :visible (bmkp-get-bookmark-in-alist (funcall bmkp-autoname-bookmark-function (point))
+ 'noerror)))
+;;;;; (define-key bmkp-delete-menu [bmkp-delete-bookmarks]
+;;;;; '(menu-item "Delete Bookmarks Here..." bmkp-delete-bookmarks
+;;;;; :help "Delete some bookmarks at point or, with `C-u', all bookmarks in the buffer"
+;;;;; :enable (mapcar #'bmkp-bookmark-name-from-record (bmkp-this-buffer-alist-only))))
+(define-key bmkp-delete-menu [bmkp-delete-bookmarks]
+ '(menu-item "Delete Bookmarks Here..." bmkp-delete-bookmarks
+ :help "Delete some bookmarks at point or, with `C-u', all bookmarks in the buffer"))
+(define-key bmkp-delete-menu [delete]
+ '(menu-item "Delete Bookmark..." bookmark-delete :help "Delete the bookmark you choose by name"))
+(define-key bmkp-delete-menu [bmkp-purge-notags-autofiles]
+ '(menu-item "Purge Autofiles with No Tags..." bmkp-purge-notags-autofiles
+ :help "Delete all autofile bookmarks that have no tags"))
+
+;; Remove vanilla `bookmark-delete' entry from main `Bookmarks' menu.
+(define-key menu-bar-bookmark-map [delete] nil)
+
+
+;; `bmkp-set-bookmark-menu' of vanilla `Bookmarks' menu: `New/Update'
+(defvar bmkp-set-bookmark-menu (make-sparse-keymap)
+ "`New/Update' submenu for menu-bar `Bookmarks' menu.")
+(define-key menu-bar-bookmark-map [set-bookmark] (cons "New/Update" bmkp-set-bookmark-menu))
+
+(defun bmkp-menu-bar-set-bookmark ()
+ "Set a bookmark, prompting for the name."
+ (interactive)
+ (call-interactively #'bmkp-bookmark-set-confirm-overwrite))
+
+(define-key bmkp-set-bookmark-menu [bmkp-make-function-bookmark]
+ '(menu-item "Function Bookmark..." bmkp-make-function-bookmark
+ :help "Create a bookmark that will invoke a function when \"jumped\" to"))
+(define-key bmkp-set-bookmark-menu [bmkp-toggle-autoname-bookmark-set]
+ '(menu-item "Autonamed Bookmark" bmkp-toggle-autonamed-bookmark-set/delete
+ :help "Set an autonamed bookmark at point"
+ :visible (not (bmkp-get-bookmark-in-alist (funcall bmkp-autoname-bookmark-function (point))
+ 'NOERROR))))
+(define-key bmkp-set-bookmark-menu [bmkp-set-bookmark-file-bookmark]
+ '(menu-item "Bookmark-File Bookmark..." bmkp-set-bookmark-file-bookmark
+ :help "Set a bookmark that loads a bookmark file when jumped to"))
+(define-key bmkp-set-bookmark-menu [bmkp-set-desktop-bookmark]
+ '(menu-item "Desktop Bookmark" bmkp-set-desktop-bookmark
+ :help "Save the current desktop as a bookmark"))
+(define-key bmkp-set-bookmark-menu [bmkp-url-target-set]
+ '(menu-item "URL Bookmark..." bmkp-url-target-set
+ :help "Set a bookmark for a given URL"))
+(define-key bmkp-set-bookmark-menu [bmkp-file-target-set]
+ '(menu-item "File Bookmark..." bmkp-file-target-set
+ :help "Set a bookmark with a given name for a given file"))
+(define-key bmkp-set-bookmark-menu [bmkp-autofile-set]
+ '(menu-item "Autofile Bookmark..." bmkp-autofile-set
+ :help "Set and automatically name a bookmark for a given file"))
+(define-key bmkp-set-bookmark-menu [bmkp-menu-bar-set-bookmark]
+ '(menu-item "Ordinary Bookmark..." bmkp-menu-bar-set-bookmark
+ :help "Set a bookmark at point" :keys "(C-x x m)")) ; Really bound to `bookmark-set'
+
+
+;; Remove vanilla `bookmark-set' from main `Bookmarks' menu.
+(define-key menu-bar-bookmark-map [set] nil)
+
+
+;; `bmkp-options-menu' of vanilla `Bookmarks' menu: `Toggle'. Reuse `bmkp-bmenu-toggle-menu'.
+(define-key menu-bar-bookmark-map [options] (cons "Toggle" bmkp-bmenu-toggle-menu))
+
+
+;; `bmkp-tags-menu' of vanilla `Bookmarks' menu: `Tags'
+
+(defvar bmkp-tags-menu (make-sparse-keymap)
+ "`Tags' submenu for menu-bar `Bookmarks' menu.")
+(define-key menu-bar-bookmark-map [tags] (cons "Tags" bmkp-tags-menu))
+
+(define-key bmkp-tags-menu [bmkp-list-all-tags]
+ '(menu-item "List All Tags" bmkp-list-all-tags :help "List all tags used for any bookmarks"))
+(define-key bmkp-tags-menu [bmkp-purge-notags-autofiles]
+ '(menu-item "Purge Autofiles with No Tags..." bmkp-purge-notags-autofiles
+ :help "Delete all autofile bookmarks that have no tags"))
+(define-key bmkp-tags-menu [bmkp-untag-a-file]
+ '(menu-item "Untag a File (Remove Some)..." bmkp-untag-a-file
+ :help "Remove some tags from autofile bookmark for a file"))
+(define-key bmkp-tags-menu [bmkp-tag-a-file]
+ '(menu-item "Tag a File (Add Some)..." bmkp-tag-a-file
+ :help "Add some tags to the autofile bookmark for a file"))
+
+(define-key bmkp-tags-menu [tags-sep1] '("--")) ;----------------------------------------------
+(define-key bmkp-tags-menu [bmkp-rename-tag]
+ '(menu-item "Rename Tag..." bmkp-rename-tag :help "Rename a tag in all bookmarks"))
+(define-key bmkp-tags-menu [bmkp-set-tag-value]
+ '(menu-item "Set Tag Value..." bmkp-set-tag-value :help "Set the tag value for a given bookmark"))
+(define-key bmkp-tags-menu [bmkp-remove-tags-from-all]
+ '(menu-item "Remove Some Tags from All..." bmkp-remove-tags-from-all
+ :help "Remove a set of tags from all bookmarks"))
+(define-key bmkp-tags-menu [bmkp-remove-tags]
+ '(menu-item "Remove Some Tags..." bmkp-remove-tags :help "Remove a set of tags from a bookmark"))
+(define-key bmkp-tags-menu [bmkp-add-tags]
+ '(menu-item "Add Some Tags..." bmkp-add-tags :help "Add a set of tags to a bookmark"))
+(define-key bmkp-tags-menu [bmkp-paste-replace-tags]
+ '(menu-item "Paste Tags (Replace)..." bmkp-paste-replace-tags
+ :help "Replace tags for a bookmark with tags copied from another"))
+(define-key bmkp-tags-menu [bmkp-paste-add-tags]
+ '(menu-item "Paste Tags (Add)..." bmkp-paste-add-tags
+ :help "Add tags to a bookmark that were previously copied from another"))
+(define-key bmkp-tags-menu [bmkp-copy-tags]
+ '(menu-item "Copy Tags..." bmkp-copy-tags
+ :help "Copy the tags from a bookmark, so you can paste them to another"))
+(define-key bmkp-tags-menu [bmkp-edit-tags]
+ '(menu-item "Edit Tags..." bmkp-edit-tags :help "Edit the tags of a bookmark"))
+
+
+;; `bmkp-jump-menu' of vanilla `Bookmarks' menu: `Jump To'
+
+(defvar bmkp-jump-menu (make-sparse-keymap)
+ "`Jump To' submenu for menu-bar `Bookmarks' menu.")
+;; Add jump menu to vanilla Emacs `Bookmarks' menu and remove the two jump commands already there.
+(define-key menu-bar-bookmark-map [jump] nil)
+(define-key menu-bar-bookmark-map [jump-other] nil)
+(define-key menu-bar-bookmark-map [bmkp-jump] (cons "Jump To" bmkp-jump-menu))
+
+;; `Jump To': Add jump menu also to the `Bookmark+' menu, and remove the two jump commands there.
+(define-key bmkp-bmenu-menubar-menu [jump] (cons "Jump To" bmkp-jump-menu))
+
+(define-key bmkp-jump-menu [bmkp-temporary-jump-other-window]
+ '(menu-item "Temporary..." bmkp-temporary-jump-other-window
+ :help "Jump to a temporary bookmark"))
+(define-key bmkp-jump-menu [bmkp-autofile-jump-other-window]
+ '(menu-item "Autofile..." bmkp-autofile-jump-other-window
+ :help "Jump to an autofile bookmark"))
+(define-key bmkp-jump-menu [bmkp-autonamed-this-buffer-jump]
+ '(menu-item "Autonamed for This Buffer..." bmkp-autonamed-this-buffer-jump
+ :help "Jump to an autonamed bookmark in this buffer"))
+(define-key bmkp-jump-menu [bmkp-autonamed-jump-other-window]
+ '(menu-item "Autonamed..." bmkp-autonamed-jump-other-window
+ :help "Jump to an autonamed bookmark"))
+(define-key bmkp-jump-menu [bmkp-specific-files-jump-other-window]
+ '(menu-item "For Specific Files..." bmkp-specific-files-jump-other-window
+ :help "Jump to a bookmark for specific files"))
+(define-key bmkp-jump-menu [bmkp-specific-buffers-jump-other-window]
+ '(menu-item "For Specific Buffers..." bmkp-specific-buffers-jump-other-window
+ :help "Jump to a bookmark for specific buffers"))
+;;;;; (define-key bmkp-jump-menu [bmkp-this-buffer-jump]
+;;;;; '(menu-item "For This Buffer..." bmkp-this-buffer-jump
+;;;;; :help "Jump to a bookmark for the current buffer"
+;;;;; :enable (mapcar #'bmkp-bookmark-name-from-record (bmkp-this-buffer-alist-only))))
+(define-key bmkp-jump-menu [bmkp-this-buffer-jump]
+ '(menu-item "For This Buffer..." bmkp-this-buffer-jump
+ :help "Jump to a bookmark for the current buffer"))
+;;;;; (when (featurep 'bookmark+-lit)
+;;;;; (define-key bmkp-jump-menu [bmkp-lighted-jump-other-window]
+;;;;; '(menu-item "Highlighted..." bmkp-lighted-jump-other-window
+;;;;; :help "Jump to a highlighted bookmark"
+;;;;; :enable (bmkp-lighted-alist-only))))
+(when (featurep 'bookmark+-lit)
+ (define-key bmkp-jump-menu [bmkp-lighted-jump-other-window]
+ '(menu-item "Highlighted..." bmkp-lighted-jump-other-window
+ :help "Jump to a highlighted bookmark")))
+(define-key bmkp-jump-menu [bmkp-jump-in-navlist-other-window]
+ '(menu-item "In Navigation List..." bmkp-jump-in-navlist-other-window
+ :help "Jump to a bookmark that is in the navigation list" :enable bmkp-nav-alist))
+
+(define-key bmkp-jump-menu [jump-sep0] '("--")) ;---------------------------------------------------
+;;;;; (define-key bmkp-jump-menu [bmkp-url-jump-other-window]
+;;;;; '(menu-item "URL..." bmkp-url-jump-other-window :help "Jump to a URL bookmark"
+;;;;; :enable (bmkp-url-alist-only)))
+(define-key bmkp-jump-menu [bmkp-url-jump-other-window]
+ '(menu-item "URL..." bmkp-url-jump-other-window :help "Jump to a URL bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-gnus-jump-other-window]
+;;;;; '(menu-item "Gnus..." bmkp-gnus-jump-other-window :help "Jump to a Gnus bookmark"
+;;;;; :enable (bmkp-gnus-alist-only)))
+(define-key bmkp-jump-menu [bmkp-gnus-jump-other-window]
+ '(menu-item "Gnus..." bmkp-gnus-jump-other-window :help "Jump to a Gnus bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-man-jump-other-window]
+;;;;; '(menu-item "Man Page..." bmkp-man-jump-other-window :help "Jump to a `man'-page bookmark"
+;;;;; :enable (bmkp-man-alist-only)))
+(define-key bmkp-jump-menu [bmkp-man-jump-other-window]
+ '(menu-item "Man Page..." bmkp-man-jump-other-window :help "Jump to a `man'-page bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-info-jump-other-window]
+;;;;; '(menu-item "Info Node..." bmkp-info-jump-other-window :help "Jump to an Info bookmark"
+;;;;; :enable (bmkp-info-alist-only)))
+(define-key bmkp-jump-menu [bmkp-info-jump-other-window]
+ '(menu-item "Info Node..." bmkp-info-jump-other-window :help "Jump to an Info bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-image-jump-other-window]
+;;;;; '(menu-item "Image..." bmkp-image-jump-other-window :help "Jump to an image-file bookmark"
+;;;;; :enable (bmkp-image-alist-only)))
+(define-key bmkp-jump-menu [bmkp-image-jump-other-window]
+ '(menu-item "Image..." bmkp-image-jump-other-window :help "Jump to an image-file bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-non-file-jump-other-window]
+;;;;; '(menu-item "Buffer (Non-File)..." bmkp-non-file-jump-other-window
+;;;;; :help "Jump to a non-file (buffer) bookmark" :enable (bmkp-non-file-alist-only)))
+(define-key bmkp-jump-menu [bmkp-non-file-jump-other-window]
+ '(menu-item "Buffer (Non-File)..." bmkp-non-file-jump-other-window
+ :help "Jump to a non-file (buffer) bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-region-jump-other-window]
+;;;;; '(menu-item "Region..." bmkp-region-jump-other-window
+;;;;; :help "Jump to a bookmark that defines the active region" :enable (bmkp-region-alist-only)))
+(define-key bmkp-jump-menu [bmkp-region-jump-other-window]
+ '(menu-item "Region..." bmkp-region-jump-other-window
+ :help "Jump to a bookmark that defines the active region"))
+;;;;; (define-key bmkp-jump-menu [bmkp-remote-file-jump-other-window]
+;;;;; '(menu-item "Remote File..." bmkp-remote-file-jump-other-window
+;;;;; :help "Jump to a remote file or directory bookmark" :enable (bmkp-remote-file-alist-only)))
+(define-key bmkp-jump-menu [bmkp-remote-file-jump-other-window]
+ '(menu-item "Remote File..." bmkp-remote-file-jump-other-window
+ :help "Jump to a remote file or directory bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-local-file-jump-other-window]
+;;;;; '(menu-item "Local File..." bmkp-local-file-jump-other-window
+;;;;; :help "Jump to a local file or directory bookmark" :enable (bmkp-local-file-alist-only)))
+(define-key bmkp-jump-menu [bmkp-local-file-jump-other-window]
+ '(menu-item "Local File..." bmkp-local-file-jump-other-window
+ :help "Jump to a local file or directory bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-file-this-dir-jump-other-window]
+;;;;; '(menu-item "File in This Dir..." bmkp-file-this-dir-jump-other-window
+;;;;; :help "Jump to a bookmark for a file or subdirectory in the `default-directory'."
+;;;;; :enable (bmkp-file-alist-only)))
+(define-key bmkp-jump-menu [bmkp-file-this-dir-jump-other-window]
+ '(menu-item "File in This Dir..." bmkp-file-this-dir-jump-other-window
+ :help "Jump to a bookmark for a file or subdirectory in the `default-directory'."))
+;;;;; (define-key bmkp-jump-menu [bmkp-file-jump-other-window]
+;;;;; '(menu-item "File..." bmkp-file-jump-other-window :help "Jump to a file or directory bookmark"
+;;;;; :enable (bmkp-file-alist-only)))
+(define-key bmkp-jump-menu [bmkp-file-jump-other-window]
+ '(menu-item "File..." bmkp-file-jump-other-window :help "Jump to a file or directory bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-dired-this-dir-jump-other-window]
+;;;;; '(menu-item "Dired for This Dir..." bmkp-dired-this-dir-jump-other-window
+;;;;; :help "Jump to a Dired bookmark for `default-directory', restoring recorded state"
+;;;;; :enable (bmkp-dired-alist-only)))
+(define-key bmkp-jump-menu [bmkp-dired-this-dir-jump-other-window]
+ '(menu-item "Dired for This Dir..." bmkp-dired-this-dir-jump-other-window
+ :help "Jump to a Dired bookmark for `default-directory', restoring recorded state"))
+;;;;; (define-key bmkp-jump-menu [bmkp-dired-jump-other-window]
+;;;;; '(menu-item "Dired..." bmkp-dired-jump-other-window
+;;;;; :help "Jump to a Dired bookmark, restoring the recorded Dired state"
+;;;;; :enable (bmkp-dired-alist-only)))
+(define-key bmkp-jump-menu [bmkp-dired-jump-other-window]
+ '(menu-item "Dired..." bmkp-dired-jump-other-window
+ :help "Jump to a Dired bookmark, restoring the recorded Dired state"))
+;;;;; (define-key bmkp-jump-menu [bmkp-variable-list-jump]
+;;;;; '(menu-item "Variable List..." bmkp-variable-list-jump :help "Jump to a variable-list bookmark"
+;;;;; :enable (bmkp-variable-list-alist-only)))
+(define-key bmkp-jump-menu [bmkp-variable-list-jump]
+ '(menu-item "Variable List..." bmkp-variable-list-jump :help "Jump to a variable-list bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-bookmark-file-jump]
+;;;;; '(menu-item "Bookmark File..." bmkp-bookmark-file-jump
+;;;;; :help "Jump to (load) a bookmark-file bookmark" :enable (bmkp-bookmark-file-alist-only)))
+(define-key bmkp-jump-menu [bmkp-bookmark-file-jump]
+ '(menu-item "Bookmark File..." bmkp-bookmark-file-jump
+ :help "Jump to (load) a bookmark-file bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-bookmark-list-jump]
+;;;;; '(menu-item "Bookmark List..." bmkp-bookmark-list-jump :help "Jump to a bookmark-list bookmark"
+;;;;; :enable (bmkp-bookmark-list-alist-only)))
+(define-key bmkp-jump-menu [bmkp-bookmark-list-jump]
+ '(menu-item "Bookmark List..." bmkp-bookmark-list-jump :help "Jump to a bookmark-list bookmark"))
+;;;;; (define-key bmkp-jump-menu [bmkp-desktop-jump]
+;;;;; '(menu-item "Desktop..." bmkp-desktop-jump :help "Jump to a desktop bookmark"
+;;;;; :enable (bmkp-desktop-alist-only)))
+(define-key bmkp-jump-menu [bmkp-desktop-jump]
+ '(menu-item "Desktop..." bmkp-desktop-jump :help "Jump to a desktop bookmark"))
+(define-key bmkp-jump-menu [bmkp-jump-to-type-other-window]
+ '(menu-item "Of Type..." bmkp-jump-to-type-other-window
+ :help "Jump to a bookmark of a type that you specify"))
+
+(define-key bmkp-jump-menu [bookmark-jump-other-window]
+ '(menu-item "Any in Other Window..." bookmark-jump-other-window
+ :help "Jump to a bookmark of any type, in another window"))
+(define-key bmkp-jump-menu [bookmark-jump]
+ '(menu-item "Any..." bookmark-jump :help "Jump to a bookmark of any type, in this window"))
+
+(define-key bmkp-jump-menu [bmkp-bmenu-jump-to-marked]
+ '(menu-item "Marked" bmkp-bmenu-jump-to-marked
+ :help "Jump to each bookmark marked `>', in another window"
+ :enable (and bmkp-bmenu-marked-bookmarks (equal (buffer-name (current-buffer))
+ bmkp-bmenu-buffer))))
+
+
+;; `bmkp-jump-tags-menu' of vanilla `Bookmarks' menu: `Jump To' > `With Tags'
+
+(defvar bmkp-jump-tags-menu (make-sparse-keymap)
+ "`With Tags' submenu for `Jump To' submenu of `Bookmarks' menu.")
+(define-key bmkp-jump-menu [bmkp-tags] (cons "With Tags" bmkp-jump-tags-menu))
+(define-key bmkp-jump-tags-menu [bmkp-file-this-dir-all-tags-regexp-jump-other-window]
+ '(menu-item "File in This Dir, All Tags Matching Regexp..."
+ bmkp-file-this-dir-all-tags-regexp-jump-other-window
+ :help "Jump to a file bookmark in this dir where each tag matches a regexp"))
+(define-key bmkp-jump-tags-menu [bmkp-file-this-dir-some-tags-regexp-jump-other-window]
+ '(menu-item "File in This Dir, Any Tag Matching Regexp..."
+ bmkp-file-this-dir-some-tags-regexp-jump-other-window
+ :help "Jump to a file bookmark in this dir where at least one tag matches a regexp"))
+(define-key bmkp-jump-tags-menu [bmkp-file-this-dir-all-tags-jump-other-window]
+ '(menu-item "File in This Dir, All Tags in Set..." bmkp-file-this-dir-all-tags-jump-other-window
+ :help "Jump to a file bookmark in this dir that has all of a set of tags that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-file-this-dir-some-tags-jump-other-window]
+ '(menu-item "File in This Dir, Any Tag in Set..." bmkp-file-this-dir-some-tags-jump-other-window
+ :help "Jump to a file bookmark in this dir that has some of a set of tags that you enter"))
+
+(define-key bmkp-jump-tags-menu [jump-sep5] '("--")) ;----------------------------------------------
+(define-key bmkp-jump-tags-menu [bmkp-file-all-tags-regexp-jump-other-window]
+ '(menu-item "File, All Tags Matching Regexp..." bmkp-file-all-tags-regexp-jump-other-window
+ :help "Jump to a file or dir bookmark where each tag matches a regexp that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-file-some-tags-regexp-jump-other-window]
+ '(menu-item "File, Any Tag Matching Regexp..." bmkp-file-some-tags-regexp-jump-other-window
+ :help "Jump to a file or dir bookmark where at least one tag matches a regexp that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-file-all-tags-jump-other-window]
+ '(menu-item "File, All Tags in Set..." bmkp-file-all-tags-jump-other-window
+ :help "Jump to a file or dir bookmark that has all of a set of tags that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-file-some-tags-jump-other-window]
+ '(menu-item "File, Any Tag in Set..." bmkp-file-some-tags-jump-other-window
+ :help "Jump to a file or dir bookmark that has some of a set of tags that you enter"))
+
+(define-key bmkp-jump-tags-menu [jump-sep4] '("--")) ;----------------------------------------------
+(define-key bmkp-jump-tags-menu [bmkp-autofile-all-tags-regexp-jump-other-window]
+ '(menu-item "Autofile, All Tags Matching Regexp..."
+ bmkp-autofile-all-tags-regexp-jump-other-window
+ :help "Jump to an autofile bookmark where each tag matches a regexp that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-autofile-some-tags-regexp-jump-other-window]
+ '(menu-item "Autofile, Any Tag Matching Regexp..."
+ bmkp-autofile-some-tags-regexp-jump-other-window
+ :help "Jump to an autofile bookmark where at least one tag matches a regexp that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-autofile-all-tags-jump-other-window]
+ '(menu-item "Autofile, All Tags in Set..."
+ bmkp-autofile-all-tags-jump-other-window
+ :help "Jump to an autofile bookmark that has all of a set of tags that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-autofile-some-tags-jump-other-window]
+ '(menu-item "Autofile, Any Tag in Set..." bmkp-autofile-some-tags-jump-other-window
+ :help "Jump to an autofile bookmark that has some of a set of tags that you enter"))
+
+(when (fboundp 'bmkp-find-file-all-tags) ; Emacs 21+
+ (define-key bmkp-jump-tags-menu [jump-sep3] '("--")) ;----------------------------------------------
+ (define-key bmkp-jump-tags-menu [bmkp-find-file-all-tags-regexp-other-window]
+ '(menu-item "Find Autofile, All Tags Matching Regexp..."
+ bmkp-find-file-all-tags-regexp-other-window
+ :help "Visit a bookmarked file where each tag matches a regexp that you enter"))
+ (define-key bmkp-jump-tags-menu [bmkp-find-file-some-tags-regexp-other-window]
+ '(menu-item "Find Autofile, Any Tag Matching Regexp..."
+ bmkp-find-file-some-tags-regexp-other-window
+ :help "Visit a bookmarked file where at least one tag matches a regexp that you enter"))
+ (define-key bmkp-jump-tags-menu [bmkp-find-file-all-tags-other-window]
+ '(menu-item "Find Autofile, All Tags in Set..."
+ bmkp-find-file-all-tags-other-window
+ :help "Visit a bookmarked file that has all of a set of tags that you enter"))
+ (define-key bmkp-jump-tags-menu [bmkp-find-file-some-tags-other-window]
+ '(menu-item "Find Autofile, Any Tag in Set..." bmkp-find-file-some-tags-other-window
+ :help "Visit a bookmarked file that has some of a set of tags that you enter")))
+
+(define-key bmkp-jump-tags-menu [jump-sep2] '("--")) ;----------------------------------------------
+(define-key bmkp-jump-tags-menu [bmkp-all-tags-regexp-jump-other-window]
+ '(menu-item "All Tags Matching Regexp..." bmkp-all-tags-regexp-jump-other-window
+ :help "Jump to a bookmark that has each tag matching a regexp that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-some-tags-regexp-jump-other-window]
+ '(menu-item "Any Tag Matching Regexp..." bmkp-some-tags-regexp-jump-other-window
+ :help "Jump to a bookmark that has at least one tag matching a regexp that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-all-tags-jump-other-window]
+ '(menu-item "All Tags in Set..." bmkp-all-tags-jump-other-window
+ :help "Jump to a bookmark that has all of a set of tags that you enter"))
+(define-key bmkp-jump-tags-menu [bmkp-some-tags-jump-other-window]
+ '(menu-item "Any Tag in Set..." bmkp-some-tags-jump-other-window
+ :help "Jump to a bookmark that has some of a set of tags that you enter"))
+
+
+;; `File' > `Find File or Autofile' submenu
+;; or, for Emacs 20-21, single item `File' > `Find File or Autofile...'.
+(if (not (fboundp 'bmkp-find-file-all-tags))
+ (define-key menu-bar-file-menu [bmkp-find-file-other-window] ; Emacs 20-21
+ '(menu-item "Find File or Autofile..." bmkp-find-file-other-window))
+ (defvar bmkp-find-file-menu (make-sparse-keymap)
+ "`Find File or Autofile' submenu for menu-bar `File' menu.")
+ (define-key menu-bar-file-menu [bmkp-find-file-menu]
+ (list 'menu-item "Find File or Autofile" bmkp-find-file-menu))
+ (define-key bmkp-find-file-menu [bmkp-find-file-all-tags-regexp-other-window]
+ '(menu-item "All Tags Matching Regexp..." bmkp-find-file-all-tags-regexp-other-window
+ :help "Visit a file or dir where each tag matches a regexp that you enter"))
+ (define-key bmkp-find-file-menu [bmkp-find-file-some-tags-regexp-other-window]
+ '(menu-item "Any Tag Matching Regexp..." bmkp-find-file-some-tags-regexp-other-window
+ :help "Jump to a file or dir bookmark where at least one tag matches a regexp that you enter"))
+ (define-key bmkp-find-file-menu [bmkp-find-file-all-tags-other-window]
+ '(menu-item "All Tags in Set..." bmkp-find-file-all-tags-other-window
+ :help "Visit a file or dir that has all of a set of tags that you enter"))
+ (define-key bmkp-find-file-menu [bmkp-find-file-some-tags-other-window]
+ '(menu-item "Any Tag in Set..." bmkp-find-file-some-tags-other-window
+ :help "Visit a file or dir that has some of a set of tags that you enter"))
+ (define-key bmkp-find-file-menu [find-file-sep2] '("--")) ;---------
+ (define-key bmkp-find-file-menu [bmkp-find-file-other-window]
+ '(menu-item "Any File or Autofile..." bmkp-find-file-other-window
+ :help "Visit a bookmarked file or directory: an autofile bookmark.")))
+
+;;;;;;;;;;;;;;;;;;;;;
+
+(provide 'bookmark+-key)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; bookmark+-key.el ends here
--- /dev/null
+;;; bookmark+-lit.el --- Bookmark highlighting for Bookmark+.
+;;
+;; Filename: bookmark+-lit.el
+;; Description: Bookmark highlighting for Bookmark+.
+;; Author: Drew Adams
+;; Maintainer: Drew Adams
+;; Copyright (C) 2010-2022, Drew Adams, all rights reserved.
+;; Created: Wed Jun 23 07:49:32 2010 (-0700)
+;; Last-Updated: Fri Jan 14 12:50:59 2022 (-0800)
+;; By: dradams
+;; Update #: 1005
+;; URL: https://www.emacswiki.org/emacs/download/bookmark%2b-lit.el
+;; Doc URL: https://www.emacswiki.org/emacs/BookmarkPlus
+;; Keywords: bookmarks, highlighting, bookmark+
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x, 26.x
+;;
+;; Features that might be required by this library:
+;;
+;; `bookmark', `pp', `pp+'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Bookmark highlighting for Bookmark+ (library `bookmark+.el').
+;;
+;; The Bookmark+ libraries are:
+;;
+;; `bookmark+.el' - main code library
+;; `bookmark+-mac.el' - Lisp macros
+;; `bookmark+-lit.el' - code for highlighting bookmarks (this file)
+;; `bookmark+-bmu.el' - code for the `*Bookmark List*'
+;; `bookmark+-1.el' - other required code (non-bmenu)
+;; `bookmark+-key.el' - key and menu bindings
+;;
+;; `bookmark+-doc.el' - documentation (comment-only file)
+;; `bookmark+-chg.el' - change log (comment-only file)
+;;
+;; This library (`bookmark+-lit.el') is a Bookmark+ option. If you
+;; want to use it then load it before loading `bookmark+.el', so
+;; that its commands can be bound to keys and menu items.
+;;
+;; The documentation (in `bookmark+-doc.el') includes how to
+;; byte-compile and install Bookmark+. The documentation is also
+;; available in these ways:
+;;
+;; 1. From the bookmark list (`C-x r l'):
+;; Use `?' to show the current bookmark-list status and general
+;; help, then click link `Doc in Commentary' or link `Doc on the
+;; Web'.
+;;
+;; 2. From the Emacs-Wiki Web site:
+;; https://www.emacswiki.org/emacs/BookmarkPlus.
+;;
+;; 3. From the Bookmark+ group customization buffer:
+;; `M-x customize-group bookmark-plus', then click link
+;; `Commentary'.
+;;
+;; (The commentary links in #1 and #3 work only if you have library
+;; `bookmark+-doc.el' in your `load-path'.)
+
+;;(@> "Index")
+;;
+;; Index
+;; -----
+;;
+;; If you have library `linkd.el' and Emacs 22 or later, load
+;; `linkd.el' and turn on `linkd-mode' now. It lets you easily
+;; navigate around the sections of this doc. Linkd mode will
+;; highlight this Index, as well as the cross-references and section
+;; headings throughout this file. You can get `linkd.el' here:
+;; https://www.emacswiki.org/emacs/download/linkd.el.
+;;
+;; (@> "Things Defined Here")
+;; (@> "Faces (Customizable)")
+;; (@> "User Options (Customizable)")
+;; (@> "Internal Variables")
+;; (@> "Functions")
+;; (@> "Menu-List (`*-bmenu-*') Commands")
+;; (@> "General Highlight Commands")
+;; (@> "Other Functions")
+
+;;(@* "Things Defined Here")
+;;
+;; Things Defined Here
+;; -------------------
+;;
+;; Commands defined here:
+;;
+;;
+;; `bmkp-bmenu-light', `bmkp-bmenu-light-marked',
+;; `bmkp-bmenu-set-lighting', `bmkp-bmenu-set-lighting-for-marked',
+;; `bmkp-bmenu-show-only-lighted-bookmarks', `bmkp-bmenu-unlight',
+;; `bmkp-bmenu-unlight-marked', `bmkp-bookmarks-lighted-at-point',
+;; `bmkp-cycle-lighted-this-buffer',
+;; `bmkp-cycle-lighted-this-buffer-other-window',
+;; `bmkp-describe-bookmark-lighted-here',
+;; `bmkp-light-autonamed-this-buffer', `bmkp-light-bookmark',
+;; `bmkp-light-bookmark-this-buffer', `bmkp-light-bookmarks',
+;; `bmkp-light-bookmarks-in-region',
+;; `bmkp-light-navlist-bookmarks',
+;; `bmkp-light-non-autonamed-this-buffer',
+;; `bmkp-light-this-buffer', `bmkp-lighted-jump',
+;; `bmkp-lighted-jump-other-window', `bmkp-lighted-jump-to-list',
+;; `bmkp-next-lighted-this-buffer',
+;; `bmkp-next-lighted-this-buffer-repeat',
+;; `bmkp-previous-lighted-this-buffer',
+;; `bmkp-previous-lighted-this-buffer-repeat',
+;; `bmkp-set-lighting-for-bookmark',
+;; `bmkp-set-lighting-for-buffer',
+;; `bmkp-set-lighting-for-this-buffer',
+;; `bmkp-toggle-auto-light-when-jump',
+;; `bmkp-toggle-auto-light-when-set',
+;; `bmkp-unlight-autonamed-this-buffer', `bmkp-unlight-bookmark',
+;; `bmkp-unlight-bookmark-here',
+;; `bmkp-unlight-bookmark-this-buffer', `bmkp-unlight-bookmarks',
+;; `bmkp-unlight-non-autonamed-this-buffer',
+;; `bmkp-unlight-this-buffer'.
+;;
+;; User options defined here:
+;;
+;; `bmkp-auto-light-relocate-when-jump-flag',
+;; `bmkp-auto-light-when-jump', `bmkp-auto-light-when-set',
+;; `bmkp-light-left-fringe-bitmap' (Emacs 22+),
+;; `bmkp-light-priorities', `bmkp-light-right-fringe-bitmap' (Emacs
+;; 22+), `bmkp-light-style-autonamed',
+;; `bmkp-light-style-non-autonamed', `bmkp-light-threshold',
+;; `bmkp-tooltip-content-function'.
+;;
+;; Faces defined here:
+;;
+;; `bmkp-light-autonamed', `bmkp-light-fringe-autonamed' (Emacs
+;; 22+), `bmkp-light-fringe-non-autonamed' (Emacs 22+),
+;; `bmkp-light-mark', `bmkp-light-non-autonamed'.
+;;
+;; Non-interactive functions defined here:
+;;
+;; `bmkp--pop-to-buffer-same-window',
+;; `bmkp-a-bookmark-lighted-at-pos',
+;; `bmkp-a-bookmark-lighted-on-this-line',
+;; `bmkp-bookmark-data-from-record',
+;; `bmkp-bookmark-name-from-record', `bmkp-bookmark-overlay-p',
+;; `bmkp-default-lighted', `bmkp-fringe-string' (Emacs 22+),
+;; `bmkp-get-lighting', `bmkp-lighted-p', `bmkp-light-face',
+;; `bmkp-light-style', `bmkp-light-style-choices',
+;; `bmkp-light-when', `bmkp-lighted-alist-only',
+;; `bmkp-lighting-attribute', `bmkp-lighting-face',
+;; `bmkp-lighting-style', `bmkp-lighting-when',
+;; `bmkp-make/move-fringe' (Emacs 22+),
+;; `bmkp-make/move-overlay-of-style', `bmkp-number-lighted',
+;; `bmkp-overlay-of-bookmark', `bmkp-read-set-lighting-args',
+;; `bmkp-set-lighting-for-bookmarks',
+;; `bmkp-this-buffer-lighted-alist-only',
+;; `bookmark-name-from-full-record', `bookmark-name-from-record'.
+;;
+;; Internal variables defined here:
+;;
+;; `bmkp-autonamed-overlays', `bmkp-last-auto-light-when-jump',
+;; `bmkp-last-auto-light-when-set', `bmkp-light-styles-alist',
+;; `bmkp-non-autonamed-overlays'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(eval-when-compile (require 'cl)) ;; case (plus, for Emacs 20: push)
+
+(require 'bookmark)
+;; bookmark-alist, bookmark-bmenu-bookmark, bookmark-completing-read, bmkp-get-bookmark,
+;; bookmark-get-position, bookmark-handle-bookmark, bookmark-maybe-load-default-file,
+;; bookmark-name-from-full-record, bookmark-name-from-record, bookmark-prop-get, bookmark-prop-set
+
+
+;; Some general Renamings.
+;;
+;; 1. Fix incompatibility introduced by gratuitous Emacs name change.
+;;
+(cond ((and (fboundp 'bookmark-name-from-record) (not (fboundp 'bookmark-name-from-full-record)))
+ (defalias 'bookmark-name-from-full-record 'bookmark-name-from-record))
+ ((and (fboundp 'bookmark-name-from-full-record) (not (fboundp 'bookmark-name-from-record)))
+ (defalias 'bookmark-name-from-record 'bookmark-name-from-full-record)))
+
+;; 2. The vanilla name of the first is misleading, as it returns only the cdr of the record.
+;; The second is for consistency.
+;;
+(defalias 'bmkp-bookmark-data-from-record 'bookmark-get-bookmark-record)
+(defalias 'bmkp-bookmark-name-from-record 'bookmark-name-from-full-record)
+
+
+(eval-when-compile
+ (or (condition-case nil
+ (load-library "bookmark+-mac") ; Use load-library to ensure latest .elc.
+ (error nil))
+ (require 'bookmark+-mac))) ; Require, so can load separately if not on `load-path'.
+;; bmkp-define-show-only-command
+
+
+;; (eval-when-compile (require 'bookmark+-bmu))
+;; bmkp-bmenu-barf-if-not-in-menu-list, bmkp-bmenu-filter-function,
+;; bmkp-bmenu-title
+
+;; (eval-when-compile (require 'bookmark+-1))
+;; bmkp-autonamed-bookmark-p, bmkp-autonamed-this-buffer-alist-only,
+;; bmkp-autoname-format, bmkp-current-nav-bookmark,
+;; bmkp-current-sort-order, bmkp-cycle-1, bmkp-default-bookmark-name,
+;; bmkp-function-bookmark-p, bmkp-get-bookmark-in-alist, bmkp-get-buffer-name, bmkp-jump-1,
+;; bmkp-latest-bookmark-alist, bmkp-marked-bookmarks-only,
+;; bmkp-msg-about-sort-order, bmkp-nav-alist, bmkp-refresh-menu-list,
+;; bmkp-remove-if, bmkp-remove-if-not, bmkp-repeat-command,
+;; bmkp-sequence-bookmark-p, bmkp-sort-omit,
+;; bmkp-specific-buffers-alist-only, bmkp-this-buffer-alist-only,
+;; bmkp-this-file/buffer-cycle-sort-comparer, bmkp-this-buffer-p
+
+(require 'pp+ nil t) ;; pp-read-expression-map
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Quiet the byte-compiler
+;;
+(defvar bmkp-autoname-format) ; In `bookmark+-1.el'.
+(defvar bmkp-bmenu-buffer) ; In `bookmark+.el'
+(defvar bmkp-current-nav-bookmark) ; In `bookmark+-1.el'.
+(defvar bmkp-latest-bookmark-alist) ; In `bookmark+-1.el'.
+(defvar bmkp-light-left-fringe-bitmap) ; Defined in this file for Emacs 22+.
+(defvar bmkp-light-right-fringe-bitmap) ; Defined in this file for Emacs 22+.
+(defvar bmkp-nav-alist) ; In `bookmark+-1.el'.
+(defvar bmkp-this-file/buffer-cycle-sort-comparer) ; In `bookmark+-1.el'.
+(defvar fringe-bitmaps) ; Built-in for Emacs 22+.
+
+
+;;(@* "Faces (Customizable)")
+;;; Faces (Customizable) ---------------------------------------------
+
+(defface bmkp-light-autonamed
+ '((((background dark)) (:background "#00004AA652F1")) ; a dark cyan
+ (t (:background "misty rose"))) ; a light pink
+ "*Face used to highlight an autonamed bookmark (except in the fringe)."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-light-autonamed-region
+ '((((background dark)) (:background "#22225F5F2222")) ; a dark green
+ (t (:background "plum"))) ; a light magenta
+ "*Face used to highlight an autonamed bookmark (except in the fringe)."
+ :group 'bookmark-plus :group 'faces)
+
+(when (fboundp 'fringe-columns)
+ (defface bmkp-light-fringe-autonamed
+ '((((background dark)) (:background "#B19E6A64B19E")) ; a dark magenta
+ (t (:background "#691DC8A2691D"))) ; a medium green
+ "*Face used to highlight an autonamed bookmark in the fringe."
+ :group 'bookmark-plus :group 'faces)
+ (defface bmkp-light-fringe-non-autonamed
+ '((((background dark)) (:background "#691DC8A2691D")) ; a medium green
+ (t (:foreground "Black" :background "Plum"))) ; a light magenta
+ "*Face used to highlight a non-autonamed bookmark in the fringe."
+ :group 'bookmark-plus :group 'faces))
+
+(defface bmkp-light-mark '((t (:background "Plum")))
+ "*Face used to mark bookmarks with highlight overrides, in bookmark list.
+This face must be combinable with face `bmkp-t-mark'."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-light-non-autonamed
+ '((((background dark)) (:background "#B19E6A64B19E")) ; a dark magenta
+ (t (:background "DarkSeaGreen1"))) ; a light green
+ "*Face used to highlight a non-autonamed bookmark (except in the fringe)."
+ :group 'bookmark-plus :group 'faces)
+
+(defface bmkp-light-non-autonamed-region
+ '((((background dark)) (:background "#BFBF1F1F2F2F")) ; a dark red
+ (t (:background "turquoise")))
+ "*Face used to highlight a non-autonamed bookmark (except in the fringe)."
+ :group 'bookmark-plus :group 'faces)
+
+;; Emacs bug # prevents making use of a face in a tooltip.
+;;
+;; (defface bmkp-tooltip-content-face
+;; '((((class color))
+;; :background "lightyellow"
+;; :foreground "black"
+;; :family "Courier")
+;; (t
+;; :family "Courier"))
+;; "Face for mouseover tooltip content for highlighted bookmarks."
+;; :group 'bookmark-plus :group 'faces :group 'tooltip)
+
+;;(@* "User Options (Customizable)")
+;;; User Options (Customizable) --------------------------------------
+
+;;;###autoload (autoload 'bmkp-auto-light-relocate-when-jump-flag "bookmark+")
+(defcustom bmkp-auto-light-relocate-when-jump-flag t
+ "*Non-nil means highlight the relocated, instead of the recorded, position.
+This has an effect only when the highlighting style for the bookmark
+is `point'."
+ :type 'boolean :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-auto-light-when-jump "bookmark+")
+(defcustom bmkp-auto-light-when-jump nil
+ "*Which bookmarks to automatically highlight when jumped to.
+NOTE: The values that specify highlighting in the current buffer
+highlight bookmarks in the buffer that is current after jumping. If
+the bookmark does not really have an associated buffer, for example a
+bookmark with a handler such as `w32-browser' that just invokes a
+separate, non-Emacs program, then the current buffer after jumping
+will be the buffer before jumping."
+ :type '(choice
+ (const :tag "Autonamed bookmark" autonamed-bookmark)
+ (const :tag "Non-autonamed bookmark" non-autonamed-bookmark)
+ (const :tag "Any bookmark" any-bookmark)
+ (const :tag "Autonamed bookmarks in buffer" autonamed-in-buffer)
+ (const :tag "Non-autonamed bookmarks in buffer" non-autonamed-in-buffer)
+ (const :tag "All bookmarks in buffer" all-in-buffer)
+ (const :tag "None (no automatic highlighting)" nil))
+ :group 'bookmark-plus)
+
+;; The value is not correct if user customizes `bmkp-auto-light-when-jump' to non-nil.
+;; So must compensate in `bmkp-toggle-auto-light-when-jump'.
+(defvar bmkp-last-auto-light-when-jump (and (not bmkp-auto-light-when-jump) 'all-in-buffer)
+ "Last value of `bmkp-auto-light-when-jump'.")
+
+;;;###autoload (autoload 'bmkp-auto-light-when-set "bookmark+")
+(defcustom bmkp-auto-light-when-set nil
+ "*Which bookmarks to automatically highlight when set."
+ :type '(choice
+ (const :tag "Autonamed bookmark" autonamed-bookmark)
+ (const :tag "Non-autonamed bookmark" non-autonamed-bookmark)
+ (const :tag "Any bookmark" any-bookmark)
+ (const :tag "Autonamed bookmarks in buffer" autonamed-in-buffer)
+ (const :tag "Non-autonamed bookmarks in buffer" non-autonamed-in-buffer)
+ (const :tag "All bookmarks in buffer" all-in-buffer)
+ (const :tag "None (no automatic highlighting)" nil))
+ :group 'bookmark-plus)
+
+;; The value is not correct if user customizes `bmkp-auto-light-when-set' to non-nil.
+;; So must compensate in `bmkp-toggle-auto-light-when-set'.
+(defvar bmkp-last-auto-light-when-set (and (not bmkp-auto-light-when-set) 'all-in-buffer)
+ "Last value of `bmkp-auto-light-when-set'.")
+
+;;;###autoload (autoload 'bmkp-light-priorities "bookmark+")
+(defcustom bmkp-light-priorities '((bmkp-autonamed-overlays . 160)
+ (bmkp-non-autonamed-overlays . 150))
+ "*Priorities of bookmark highlighting overlay types.
+As an idea, `isearch' uses 1000 and 1001."
+ :group 'bookmark-plus :type '(alist :key-type symbol :value-type integer))
+
+;; Not used for Emacs 20-21 or Emacs built without fringe support.
+(when (and (fboundp 'fringe-columns) (boundp 'fringe-bitmaps))
+ (defcustom bmkp-light-left-fringe-bitmap 'left-triangle
+ "*Symbol for the left fringe bitmap to use to highlight a bookmark.
+This option is not used for Emacs versions before Emacs 22."
+ :type (cons 'choice (mapcar (lambda (bb) (list 'const bb)) fringe-bitmaps))
+ :group 'bookmark-plus)
+
+ ;; Not used for Emacs 20-21 or Emacs built without fringe support.
+ (defcustom bmkp-light-right-fringe-bitmap 'right-triangle
+ "*Symbol for the right fringe bitmap to use to highlight a bookmark.
+This option is not used for Emacs versions before Emacs 22."
+ :type (cons 'choice (mapcar (lambda (bb) (list 'const bb)) fringe-bitmaps))
+ :group 'bookmark-plus))
+
+;; Must be before any options that use it.
+(defvar bmkp-light-styles-alist (append '(("Region" . region)
+ ("Line Beginning" . bol)
+ ("Position" . point)
+ ("Line" . line)
+ ("None" . none))
+ (and (fboundp 'fringe-columns)
+ '(("Left Fringe" . lfringe)
+ ("Right Fringe" . rfringe)
+ ("Left Fringe + Line" . line+lfringe)
+ ("Right Fringe + Line" . line+rfringe))))
+ "Alist of highlighting styles. Key: string description. Value: symbol.")
+
+;; Must be before options that use it.
+(defun bmkp-light-style-choices ()
+ "Return custom `:type' used for bookmark highlighting style choices."
+ (cons 'choice
+ (mapcar (lambda (xx) (list 'const :tag (car xx) (cdr xx))) bmkp-light-styles-alist)))
+
+;;;###autoload (autoload 'bmkp-light-style-autonamed "bookmark+")
+(defcustom bmkp-light-style-autonamed (if (not (fboundp 'fringe-columns)) ; Emacs 20-21.
+ 'line
+ 'line+lfringe)
+ "*Default highlight style for autonamed bookmarks."
+ :group 'bookmark-plus :type (bmkp-light-style-choices))
+
+;;;###autoload (autoload 'bmkp-light-style-non-autonamed "bookmark+")
+(defcustom bmkp-light-style-non-autonamed (if (not (fboundp 'fringe-columns)) ; Emacs 20-21.
+ 'line
+ 'line+rfringe)
+ "*Default highlight style for non-autonamed bookmarks."
+ :group 'bookmark-plus :type (bmkp-light-style-choices))
+
+;;;###autoload (autoload 'bmkp-light-style-autonamed-region "bookmark+")
+(defcustom bmkp-light-style-autonamed-region 'region
+ "*Default highlight style for autonamed region bookmarks."
+ :group 'bookmark-plus :type (bmkp-light-style-choices))
+
+;;;###autoload (autoload 'bmkp-light-style-non-autonamed-region "bookmark+")
+(defcustom bmkp-light-style-non-autonamed-region 'region
+ "*Default highlight style for non-autonamed region bookmarks."
+ :group 'bookmark-plus :type (bmkp-light-style-choices))
+
+;;;###autoload (autoload 'bmkp-light-threshold "bookmark+")
+(defcustom bmkp-light-threshold 100000
+ "*Maximum number of bookmarks to highlight."
+ :type 'integer :group 'bookmark-plus)
+
+;;;###autoload (autoload 'bmkp-tooltip-content-function "bookmark+")
+(defcustom bmkp-tooltip-content-function 'bmkp-bookmark-description
+ "Function providing mouseover tooltip content for highlighted bookmarks.
+It should accept a bookmark name or record as its first arg and return
+a value acceptable as a `help-echo' property value.
+
+One alternative to the default value of `bmkp-bookmark-description' is
+`bmkp-annotation-or-bookmark-description', which shows the bookmark
+annotation if there is one, or the full description if not.
+
+To prevent showing any tooltip you can use a function, such as
+`ignore', that returns nil."
+ :type 'function :group 'bookmark-plus :group 'tooltip)
+
+;;(@* "Internal Variables")
+;;; Internal Variables -----------------------------------------------
+
+(defvar bmkp-autonamed-overlays nil
+ "Overlays used to highlight autonamed bookmarks.")
+
+(defvar bmkp-non-autonamed-overlays nil
+ "Overlays used to highlight non-autonamed bookmarks.")
+
+;;(@* "Functions")
+;;; Functions --------------------------------------------------------
+
+
+;;(@* "Menu-List (`*-bmenu-*') Commands")
+;; *** Menu-List (`*-bmenu-*') Commands ***
+
+;;;###autoload (autoload 'bmkp-bmenu-show-only-lighted-bookmarks "bookmark+")
+(bmkp-define-show-only-command lighted "Display (only) the highlighted bookmarks." ; `H S' in bookmark list
+ bmkp-lighted-alist-only)
+
+;;;###autoload (autoload 'bmkp-bmenu-light "bookmark+")
+(defun bmkp-bmenu-light () ; `H H' in bookmark list
+ "Highlight the location of this line's bookmark."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-light-bookmark (bookmark-bmenu-bookmark) nil nil 'MSG))
+
+;;;###autoload (autoload 'bmkp-bmenu-light-marked "bookmark+")
+(defun bmkp-bmenu-light-marked (&optional parg msgp) ; `H > H' in bookmark list
+ "Highlight the marked bookmarks."
+ (interactive (list 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (when msgp (message "Highlighting marked bookmarks..."))
+ (let ((marked (bmkp-marked-bookmarks-only)))
+ (unless marked (error "No marked bookmarks"))
+ (dolist (bmk marked) (bmkp-light-bookmark bmk)))
+ (when msgp (message "Highlighting marked bookmarks...done")))
+
+;;;###autoload (autoload 'bmkp-bmenu-unlight "bookmark+")
+(defun bmkp-bmenu-unlight () ; `H U' in bookmark list
+ "Unhighlight the location of this line's bookmark."
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-unlight-bookmark (bookmark-bmenu-bookmark) 'NOERROR))
+
+;;;###autoload (autoload 'bmkp-bmenu-unlight-marked "bookmark+")
+(defun bmkp-bmenu-unlight-marked (&optional parg msgp) ; `H > U' in bookmark list
+ "Unhighlight the marked bookmarks."
+ (interactive (list 'MSG))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (when msgp (message "Unhighlighting marked bookmarks..."))
+ (let ((marked (bmkp-marked-bookmarks-only)))
+ (unless marked (error "No marked bookmarks"))
+ (dolist (bmk marked) (bmkp-unlight-bookmark bmk t)))
+ (when msgp (message "Unhighlighting marked bookmarks...done")))
+
+;;;###autoload (autoload 'bmkp-bmenu-set-lighting "bookmark+")
+(defun bmkp-bmenu-set-lighting (style face when &optional msgp) ; `H +' in bookmark list
+ "Set the `lighting' entry for this line's bookmark.
+You are prompted for the highlight STYLE, FACE, and condition (WHEN)
+that make up the property-list value of the `lighting' entry."
+ (interactive
+ (let* ((bmk (bookmark-bmenu-bookmark))
+ (bmk-style (bmkp-lighting-style bmk))
+ (bmk-face (bmkp-lighting-face bmk))
+ (bmk-when (bmkp-lighting-when bmk)))
+ (append (bmkp-read-set-lighting-args
+ (and bmk-style (format "%s" (car (rassq bmk-style bmkp-light-styles-alist))))
+ (and bmk-face (format "%S" bmk-face))
+ (and bmk-when (format "%S" bmk-when)))
+ '(MSG))))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (bmkp-set-lighting-for-bookmark (bookmark-bmenu-bookmark) style face when 'MSG))
+
+;;;###autoload (autoload 'bmkp-bmenu-set-lighting-for-marked "bookmark+")
+(defun bmkp-bmenu-set-lighting-for-marked (style face when &optional msgp) ; `H > +' in bookmark list
+ "Set the `lighting' entry for the marked bookmarks.
+You are prompted for the highlight STYLE, FACE, and condition (WHEN)."
+ (interactive (append (bmkp-read-set-lighting-args) '(MSG)))
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (when msgp (message "Setting highlighting..."))
+ (let ((marked (bmkp-marked-bookmarks-only))
+ (curr-bmk (bookmark-bmenu-bookmark)))
+ (unless marked (error "No marked bookmarks"))
+ (dolist (bmk marked)
+ (bookmark-prop-set bmk 'lighting (if (or face style when)
+ `(,@(and face (not (eq face 'auto)) `(:face ,face))
+ ,@(and style (not (eq style 'none)) `(:style ,style))
+ ,@(and when (not (eq when 'auto)) `(:when ,when)))
+ ())))
+ (when (get-buffer-create bmkp-bmenu-buffer) (bmkp-refresh-menu-list curr-bmk)))
+ (when msgp (message "Setting highlighting...done")))
+
+
+;;(@* "General Highlight Commands")
+;; *** General Highlight Commands ***
+
+;;;###autoload (autoload 'bmkp-bookmarks-lighted-at-point "bookmark+")
+(defun bmkp-bookmarks-lighted-at-point (&optional position fullp msgp) ; `C-x p ='
+ "Return a list of the bookmarks highlighted at point.
+Include only those in the current bookmark list (`bookmark-alist').
+With no prefix arg, return the bookmark names.
+With a prefix arg, return the full bookmark data.
+Interactively, display the info.
+Non-interactively:
+ Use the bookmarks at optional arg POSITION (default: point).
+ Optional arg FULLP means return full bookmark data.
+ Optional arg MSGP means display the info."
+ (interactive (list (point) current-prefix-arg 'MSG))
+ (unless position (setq position (point)))
+ (let ((bmks ())
+ bmk)
+ (dolist (ov (overlays-at position))
+ (when (setq bmk (overlay-get ov 'bookmark))
+ (when (setq bmk (bmkp-get-bookmark-in-alist bmk 'NOERROR)) ; Ensure it's in current bookmark list.
+ (push (if fullp bmk (bmkp-bookmark-name-from-record bmk)) bmks))))
+ (if (not fullp)
+ (when msgp (message "%s" bmks))
+ (setq bmks (mapcar #'bmkp-get-bookmark bmks))
+ (when msgp (pp-eval-expression 'bmks)))
+ bmks))
+
+;;;###autoload (autoload 'bmkp-toggle-auto-light-when-jump "bookmark+")
+(defun bmkp-toggle-auto-light-when-jump (&optional msgp) ; Not bound.
+ "Toggle automatic bookmark highlighting when a bookmark is jumped to.
+Set option `bmkp-auto-light-when-jump' to nil if non-nil, and to its
+last non-nil value if nil."
+ (interactive "p")
+ (when (and bmkp-auto-light-when-jump bmkp-last-auto-light-when-jump) ; Compensate for wrong default
+ (setq bmkp-last-auto-light-when-jump nil))
+ (setq bmkp-last-auto-light-when-jump
+ (prog1 bmkp-auto-light-when-jump ; Swap
+ (setq bmkp-auto-light-when-jump bmkp-last-auto-light-when-jump)))
+ (when msgp (message "Automatic highlighting of bookmarks when jumping is now %s"
+ (if bmkp-auto-light-when-jump
+ (upcase (symbol-name bmkp-auto-light-when-jump))
+ "OFF"))))
+
+;;;###autoload (autoload 'bmkp-lighted-jump "bookmark+")
+(defun bmkp-lighted-jump (bookmark-name &optional flip-use-region-p) ; `C-x j h'
+ "Jump to a highlighted bookmark.
+This is a specialization of `bookmark-jump' - see that, in particular
+for info about using a prefix argument."
+ (interactive
+ (let ((alist (bmkp-lighted-alist-only)))
+ (unless alist (error "No highlighted bookmarks"))
+ (list (bookmark-completing-read "Jump to highlighted bookmark" nil alist) current-prefix-arg)))
+ (bmkp-jump-1 bookmark-name 'bmkp--pop-to-buffer-same-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-lighted-jump-other-window "bookmark+")
+(defun bmkp-lighted-jump-other-window (bookmark-name &optional flip-use-region-p) ; `C-x 4 j h'
+ "Jump to a highlighted bookmark in another window.
+See `bmkp-lighted-jump'."
+ (interactive
+ (let ((alist (bmkp-lighted-alist-only)))
+ (unless alist (error "No highlighted bookmarks"))
+ (list (bookmark-completing-read "Jump to highlighted bookmark in another window" nil alist)
+ current-prefix-arg)))
+ (bmkp-jump-1 bookmark-name 'bmkp-select-buffer-other-window flip-use-region-p))
+
+;;;###autoload (autoload 'bmkp-lighted-jump-to-list "bookmark+")
+(defun bmkp-lighted-jump-to-list (bookmark &optional position msgp) ; Not bound.
+ "Jump to location in `*Bookmark List*' for a lighted bookmark at point.
+You are prompted for BOOKMARK (a bookmark name).
+Completion candidates are the lighted bookmarks at point."
+ (interactive (let* ((bmks (bmkp-bookmarks-lighted-at-point (point) nil 'MSG))
+ (IGNORE (unless bmks (error "No highlighted bookmarks at point")))
+ (bmk (bookmark-completing-read "Bookmark" (car bmks) bmks)))
+ (list bmk (point) t)))
+ (pop-to-buffer (get-buffer-create bmkp-bmenu-buffer))
+ (bookmark-bmenu-list)
+ (bmkp-bmenu-goto-bookmark-named (setq bmkp-last-bmenu-bookmark bookmark)))
+
+;;;###autoload (autoload 'bmkp-unlight-bookmark "bookmark+")
+(defun bmkp-unlight-bookmark (bookmark &optional noerrorp msgp) ; Not bound
+ "Unhighlight BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record."
+ (interactive
+ (let ((lighted-bmks (bmkp-lighted-alist-only)))
+ (unless lighted-bmks (error "No highlighted bookmarks"))
+ (list (bookmark-completing-read "UNhighlight bookmark" (bmkp-default-lighted) lighted-bmks)
+ nil
+ 'MSG)))
+ (let* ((bmk (bmkp-get-bookmark bookmark 'NOERROR))
+ (bmk-name (bmkp-bookmark-name-from-record bmk))
+ (autonamedp (and bmk (bmkp-autonamed-bookmark-p bmk))))
+ (when bmk ; Skip bad bookmark, but not already highlighted bookmark.
+ (unless (or noerrorp (bmkp-lighted-p bmk-name)) (error "Bookmark `%s' is not highlighted" bmk-name))
+ (dolist (ov (if autonamedp bmkp-autonamed-overlays bmkp-non-autonamed-overlays))
+ (when (eq bmk (overlay-get ov 'bookmark)) (delete-overlay ov)))) ; Check full bookmark, not name.
+ (when msgp (message "UNhighlighted bookmark `%s'" bmk-name))))
+
+;;;###autoload (autoload 'bmkp-unlight-bookmark-here "bookmark+")
+(defun bmkp-unlight-bookmark-here (&optional noerrorp msgp) ; `C-x p C-u'
+ "Unhighlight a bookmark at point or the same line (in that order)."
+ (interactive (list nil 'MSG))
+ (let ((bmk (or (bmkp-a-bookmark-lighted-at-pos) (bmkp-a-bookmark-lighted-on-this-line))))
+ (unless bmk (error "No highlighted bookmark on this line"))
+ (bmkp-unlight-bookmark bmk noerrorp msgp)))
+
+;;;###autoload (autoload 'bmkp-unlight-bookmark-this-buffer "bookmark+")
+(defun bmkp-unlight-bookmark-this-buffer (bookmark &optional noerrorp msgp) ; `C-x p u'
+ "Unhighlight a BOOKMARK in this buffer.
+BOOKMARK is a bookmark name or a bookmark record.
+With a prefix arg, choose from all lighted bookmarks, not just those
+in this buffer."
+ (interactive
+ (let ((lighted-bmks (if current-prefix-arg
+ (bmkp-lighted-alist-only)
+ (bmkp-this-buffer-lighted-alist-only)))
+ (msg-suffix (if current-prefix-arg "" " in this buffer")))
+ (unless lighted-bmks (error "No highlighted bookmarks%s" msg-suffix))
+ (list (bookmark-completing-read (format "UNhighlight bookmark%s in this buffer" msg-suffix)
+ (bmkp-default-lighted)
+ lighted-bmks
+ nil
+ nil
+ 'USE-NIL-ALIST-P)
+ nil
+ 'MSG)))
+ (bmkp-unlight-bookmark bookmark noerrorp msgp))
+
+;;;###autoload (autoload 'bmkp-unlight-bookmarks "bookmark+")
+(defun bmkp-unlight-bookmarks (&optional overlays-symbols this-buffer-p msgp) ; `C-x p U'
+ "Unhighlight lighted bookmarks.
+A prefix argument determines which bookmarks to unhighlight:
+ none - Current buffer, all lighted bookmarks.
+ >= 0 - Current buffer, only autonamed lighted bookmarks.
+ < 0 - Current buffer, only non-autonamed lighted bookmarks.
+ C-u - All buffers (all lighted bookmarks)."
+ (interactive (list (cond ((or (not current-prefix-arg) (consp current-prefix-arg))
+ '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays))
+ ((natnump current-prefix-arg) '(bmkp-autonamed-overlays))
+ (current-prefix-arg '(bmkp-non-autonamed-overlays)))
+ (or (not current-prefix-arg) (atom current-prefix-arg))
+ 'MSG))
+ (unless overlays-symbols
+ (setq overlays-symbols '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays)))
+ (let ((count 0)
+ (count-auto 0)
+ (count-non-auto 0)
+ (this-buf (current-buffer)))
+ (dolist (ov-symb overlays-symbols)
+ (dolist (ov (symbol-value ov-symb))
+ (let ((ov-buf (overlay-buffer ov)))
+ (when (and ov-buf (or (not this-buffer-p) (eq ov-buf this-buf)))
+ (when (eq 'bmkp-autonamed-overlays ov-symb)
+ (setq count-auto (1+ count-auto)
+ count (1+ count)))
+ (when (eq 'bmkp-non-autonamed-overlays ov-symb)
+ (setq count-non-auto (1+ count-non-auto)
+ count (1+ count)))
+ (delete-overlay ov)))))
+ (when msgp (message "UNhighlighted %d bookmarks %s: %d autonamed, %d other"
+ count (if this-buffer-p "in this buffer" "(all buffers)")
+ count-auto count-non-auto))))
+
+;;;###autoload (autoload 'bmkp-unlight-autonamed-this-buffer "bookmark+")
+(defun bmkp-unlight-autonamed-this-buffer (&optional everywherep) ; Not bound
+ "Unhighlight autonamed bookmarks.
+No prefix arg: unhighlight them only in the current buffer.
+Prefix arg, unhighlight them everywhere."
+ (interactive "P")
+ (bmkp-unlight-bookmarks '(bmkp-autonamed-overlays) (not everywherep)))
+
+;;;###autoload (autoload 'bmkp-unlight-non-autonamed-this-buffer "bookmark+")
+(defun bmkp-unlight-non-autonamed-this-buffer (&optional everywherep) ; Not bound
+ "Unhighlight non-autonamed bookmarks.
+No prefix arg: unhighlight them only in the current buffer.
+Prefix arg, unhighlight them everywhere."
+ (interactive "P")
+ (bmkp-unlight-bookmarks '(bmkp-non-autonamed-overlays) (not everywherep)))
+
+;;;###autoload (autoload 'bmkp-unlight-this-buffer "bookmark+")
+(defun bmkp-unlight-this-buffer () ; Not bound
+ "Unhighlight all bookmarks in the current buffer."
+ (interactive)
+ (bmkp-unlight-bookmarks))
+
+;;;###autoload (autoload 'bmkp-toggle-auto-light-when-set "bookmark+")
+(defun bmkp-toggle-auto-light-when-set (&optional msgp) ; Not bound.
+ "Toggle automatic bookmark highlighting when a bookmark is set.
+Set option `bmkp-auto-light-when-set' to nil if non-nil, and to its
+last non-nil value if nil."
+ (interactive "p")
+ (when (and bmkp-auto-light-when-set bmkp-last-auto-light-when-set) ; Compensate for wrong default
+ (setq bmkp-last-auto-light-when-set nil))
+ (setq bmkp-last-auto-light-when-set (prog1 bmkp-auto-light-when-set ; Swap
+ (setq bmkp-auto-light-when-set bmkp-last-auto-light-when-set)))
+ (when msgp (message "Automatic highlighting of bookmarks when setting is now %s"
+ (if bmkp-auto-light-when-set
+ (upcase (symbol-name bmkp-auto-light-when-set))
+ "OFF"))))
+
+;;;###autoload (autoload 'bmkp-set-lighting-for-bookmark "bookmark+")
+(defun bmkp-set-lighting-for-bookmark (bookmark-name style face when &optional msgp light-now-p) ; Not bound
+ "Set the `lighting' entry for bookmark BOOKMARK-NAME.
+You are prompted for the bookmark, highlight STYLE, FACE, and
+condition (WHEN) that make up the property-list value of the
+`lighting' entry.
+
+With a prefix argument, do not highlight now.
+
+Non-interactively:
+STYLE, FACE, and WHEN are as for a bookmark's `lighting' entry
+ properties, or nil if no such property.
+Non-nil MSGP means display a highlighting progress message.
+Non-nil LIGHT-NOW-P means apply the highlighting now."
+ (interactive
+ (let* ((bmk (bookmark-completing-read "Highlight bookmark"
+ (or (bmkp-default-lighted) (bmkp-default-bookmark-name))))
+ (bmk-style (bmkp-lighting-style bmk))
+ (bmk-face (bmkp-lighting-face bmk))
+ (bmk-when (bmkp-lighting-when bmk)))
+ (append (list bmk)
+ (bmkp-read-set-lighting-args
+ (and bmk-style (format "%s" (car (rassq bmk-style bmkp-light-styles-alist))))
+ (and bmk-face (format "%S" bmk-face))
+ (and bmk-when (format "%S" bmk-when)))
+ (list 'MSGP (not current-prefix-arg)))))
+ (when msgp (message "Setting highlighting..."))
+ (bookmark-prop-set bookmark-name 'lighting (if (or face style when)
+ `(,@(and face (not (eq face 'auto)) `(:face ,face))
+ ,@(and style (not (eq style 'none)) `(:style ,style))
+ ,@(and when (not (eq when 'auto)) `(:when ,when)))
+ ()))
+ (when (get-buffer-create bmkp-bmenu-buffer) (bmkp-refresh-menu-list bookmark-name))
+ (when msgp (message "Setting highlighting...done"))
+ (when light-now-p (bmkp-light-bookmark bookmark-name nil nil msgp))) ; This msg is more informative.
+
+;;;###autoload (autoload 'bmkp-set-lighting-for-buffer "bookmark+")
+(defun bmkp-set-lighting-for-buffer (buffer style face when &optional msgp light-now-p) ; Not bound
+ "Set the `lighting' entry for each of the bookmarks for BUFFER.
+You are prompted for the highlight STYLE, FACE, and condition (WHEN).
+With a prefix argument, do not highlight now.
+
+Non-interactively:
+STYLE, FACE, and WHEN are as for a bookmark's `lighting' entry
+ properties, or nil if no such property.
+Non-nil MSGP means display a highlighting progress message.
+Non-nil LIGHT-NOW-P means apply the highlighting now."
+ (interactive (append (list (bmkp-completing-read-buffer-name))
+ (bmkp-read-set-lighting-args)
+ (list 'MSGP (not current-prefix-arg))))
+ (bmkp-set-lighting-for-bookmarks
+ (let ((bmkp-last-specific-buffer buffer)) (bmkp-last-specific-buffer-alist-only))
+ style face when msgp light-now-p))
+
+;;;###autoload (autoload 'bmkp-set-lighting-for-this-buffer "bookmark+")
+(defun bmkp-set-lighting-for-this-buffer (style face when &optional msgp light-now-p) ; Not bound
+ "Set the `lighting' entry for each of the bookmarks for this buffer.
+You are prompted for the highlight STYLE, FACE, and condition (WHEN).
+With a prefix argument, do not highlight now.
+
+Non-interactively:
+STYLE, FACE, and WHEN are as for a bookmark's `lighting' entry
+ properties, or nil if no such property.
+Non-nil MSGP means display a highlighting progress message.
+Non-nil LIGHT-NOW-P means apply the highlighting now."
+ (interactive (append (bmkp-read-set-lighting-args) (list 'MSGP (not current-prefix-arg))))
+ (bmkp-set-lighting-for-bookmarks (bmkp-this-buffer-alist-only) style face when msgp light-now-p))
+
+(defun bmkp-set-lighting-for-bookmarks (alist style face when &optional msgp light-now-p)
+ "Set the `lighting' entry for each of the bookmarks in ALIST.
+STYLE, FACE, and WHEN are as for a bookmark's `lighting' entry
+ properties, or nil if no such property.
+Non-nil MSGP means display a highlighting progress message.
+Non-nil LIGHT-NOW-P means apply the highlighting now."
+ (when msgp (message "Setting highlighting..."))
+ (dolist (bmk alist) (bmkp-set-lighting-for-bookmark bmk style face when)) ; No MSGP arg here.
+ (when msgp (message "Setting highlighting...done"))
+ (when light-now-p (bmkp-light-bookmarks alist nil msgp))) ; Do separately so we get its message.
+
+;;;###autoload (autoload 'bmkp-light-bookmark "bookmark+")
+(defun bmkp-light-bookmark (bookmark &optional style face msgp pointp) ; Not bound
+ "Highlight BOOKMARK.
+With a prefix arg you are prompted for the style and/or face to use:
+ Plain prefix arg (`C-u'): prompt for both style and face.
+ Numeric non-negative arg: prompt for face.
+ Numeric negative arg: prompt for style.
+
+Non-interactively:
+ BOOKMARK is a bookmark name or a bookmark record, or it is ignored.
+ STYLE and FACE override the defaults.
+ POINT-P non-nil means highlight point rather than the recorded
+ bookmark position."
+ (interactive
+ (let* ((bmk (bookmark-completing-read "Highlight bookmark" (bmkp-default-bookmark-name)))
+ (sty (and current-prefix-arg (or (consp current-prefix-arg)
+ (<= (prefix-numeric-value current-prefix-arg) 0))
+ (cdr (assoc (let ((completion-ignore-case t))
+ (completing-read
+ "Style: " bmkp-light-styles-alist nil t nil nil
+ (and (bmkp-lighting-style bmk)
+ (format "%s" (car (rassq (bmkp-lighting-style bmk)
+ bmkp-light-styles-alist))))))
+ bmkp-light-styles-alist))))
+ (fac (and current-prefix-arg (or (consp current-prefix-arg)
+ (natnump (prefix-numeric-value current-prefix-arg)))
+ (not (member sty '(lfringe rfringe none))) ; No face possible for these.
+ (condition-case nil ; Emacs 22+ accepts a default.
+ (read-face-name "Face: " (format "%S" (bmkp-lighting-face bmk)))
+ (wrong-number-of-arguments (read-face-name "Face: "))))))
+ (list bmk sty fac 'MSG)))
+ (let* ((bmkp-use-region nil) ; Inhibit region handling.
+ (bmk (bmkp-get-bookmark bookmark (not msgp))) ; Error if interactive.
+ (bmk-name (bmkp-bookmark-name-from-record bmk))
+ (pos (and bmk (bookmark-get-position bmk)))
+ (buf (and bmk (bmkp-get-buffer-name bmk)))
+ (autonamedp (and bmk (bmkp-autonamed-bookmark-p bmk)))
+ (styl (or style (and bmk (bmkp-light-style bmk))))
+ (fac (or face (and bmk
+ (not (member styl '(lfringe rfringe none)))
+ (bmkp-light-face bmk))))
+ (passes-when-p (and bmk (or face
+ style ; Always highlight if changed face or style.
+ (bmkp-light-when bmk))))
+ (nb-lit (bmkp-number-lighted))
+ bmk-ov)
+ (catch 'bmkp-light-bookmark
+ (when bmk ; Just skip bad bookmark if not interactive.
+ (cond ((setq bmk-ov (bmkp-overlay-of-bookmark bmk)) ; Already highlighted.
+ (if (not (or style face))
+ (when msgp ; No-op batch.
+ (error "Already highlighted - use prefix arg to change"))
+ (when style (bmkp-make/move-overlay-of-style style pos autonamedp bmk bmk-ov))
+ (when (and face (not (memq styl '(lfringe rfringe none))))
+ (overlay-put bmk-ov 'face face)))
+ (when msgp (message "%sighlighted bookmark `%s'" (if bmk-ov "H" "UNh") bmk-name)))
+ (passes-when-p
+ (save-excursion
+
+ ;; See note in comments of `bmkp-light-bookmarks' - same considerations here.
+ ;; (let ((bmkp-jump-display-function nil)) (bookmark-handle-bookmark bmk))
+ ;;
+ (with-current-buffer (or (and buf (get-buffer buf))
+ (current-buffer))
+
+ ;; POINTP is non-nil when `bmkp-light-bookmark' is called from
+ ;; `bookmark--jump-via'.
+ (when (and pointp bmkp-auto-light-relocate-when-jump-flag)
+ (setq pos (point)))
+ (when (and pos (< pos (point-max)))
+ (let ((ov (bmkp-make/move-overlay-of-style styl pos autonamedp bmk)))
+ (when ov ; nil means `none' style.
+ (let ((ovs (if autonamedp
+ 'bmkp-autonamed-overlays
+ 'bmkp-non-autonamed-overlays)))
+ (push ov (symbol-value ovs)))
+ (when (and (not (bmkp-lighted-p bmk))
+ (> (setq nb-lit (1+ nb-lit)) bmkp-light-threshold))
+ (setq nb-lit (1- nb-lit))
+ (throw 'bmkp-light-bookmark bmk))
+ (overlay-put ov 'priority
+ (or (cdr (assoc (if autonamedp
+ 'bmkp-autonamed-overlays
+ 'bmkp-non-autonamed-overlays)
+ bmkp-light-priorities))
+ (apply #'min (mapcar #'cdr bmkp-light-priorities))))
+ (unless (memq styl '(lfringe rfringe none)) (overlay-put ov 'face fac))
+ (overlay-put ov 'evaporate t)
+ (overlay-put ov 'category 'bookmark-plus)
+ (overlay-put ov 'bookmark bmk)) ; Use full bookmark, because name can change.
+ (when msgp
+ (message "%sighlighted bookmark `%s'" (if ov "H" "UNh") bmk-name)))))))
+ (t
+ (when msgp (message "Bookmark's condition canceled highlighting"))))))))
+
+;;;###autoload (autoload 'bmkp-light-bookmark-this-buffer "bookmark+")
+(defun bmkp-light-bookmark-this-buffer (bookmark &optional style face msgp) ; `C-x p h'
+ "Highlight a BOOKMARK in the current buffer.
+With a prefix arg you are prompted for the style and/or face to use:
+ Plain prefix arg (`C-u'): prompt for both style and face.
+ Numeric non-negative arg: prompt for face.
+ Numeric negative arg: prompt for style.
+See `bmkp-light-bookmark' for argument descriptions."
+ (interactive
+ (let* ((bmk (bookmark-completing-read "Highlight bookmark"
+ nil
+ (bmkp-this-buffer-alist-only)
+ nil
+ nil
+ 'USE-NIL-ALIST-P))
+ (sty (and current-prefix-arg (or (consp current-prefix-arg)
+ (<= (prefix-numeric-value current-prefix-arg) 0))
+ (cdr (assoc (let ((completion-ignore-case t))
+ (completing-read
+ "Style: " bmkp-light-styles-alist nil t nil nil
+ (and (bmkp-lighting-style bmk)
+ (format "%s" (car (rassq (bmkp-lighting-style bmk)
+ bmkp-light-styles-alist))))))
+ bmkp-light-styles-alist))))
+ (fac (and current-prefix-arg (or (consp current-prefix-arg)
+ (natnump (prefix-numeric-value current-prefix-arg)))
+ (not (member sty '(lfringe rfringe none))) ; No face possible for these.
+ (condition-case nil ; Emacs 22+ accepts a default.
+ (read-face-name "Face: " (format "%S" (bmkp-lighting-face bmk)))
+ (wrong-number-of-arguments (read-face-name "Face: "))))))
+ (list bmk sty fac 'MSG)))
+ (bmkp-light-bookmark bookmark style face msgp))
+
+;;;###autoload (autoload 'bmkp-light-bookmarks "bookmark+")
+(defun bmkp-light-bookmarks (&optional alist overlays-symbols msgp) ; `C-x p H'
+ "Highlight bookmarks.
+A prefix argument determines which bookmarks to highlight:
+ none - Current buffer, all bookmarks.
+ = 0 - Current buffer, highlighted bookmarks only (rehighlight).
+ > 0 - Current buffer, autonamed bookmarks only.
+ < 0 - Current buffer, non-autonamed bookmarks only.
+ C-u - All buffers (all bookmarks) - after confirmation.
+ C-u C-u - Navlist (all bookmarks).
+
+Non-interactively, ALIST is the alist of bookmarks to highlight.
+It must be provided: if nil then do not highlight any bookmarks."
+ (interactive
+ (list (cond ((not current-prefix-arg) (bmkp-this-buffer-alist-only))
+ ((consp current-prefix-arg) (if (> (prefix-numeric-value current-prefix-arg) 4)
+ bmkp-nav-alist
+ (unless (y-or-n-p
+ "Confirm highlighting bookmarks in ALL buffers ")
+ (error "Canceled highlighting"))
+ (bmkp-specific-buffers-alist-only
+ (mapcar #'buffer-name (buffer-list)))))
+ ((> current-prefix-arg 0) (bmkp-autonamed-this-buffer-alist-only))
+ ((< current-prefix-arg 0) (bmkp-remove-if #'bmkp-autonamed-bookmark-p
+ (bmkp-this-buffer-alist-only)))
+ ((= current-prefix-arg 0) (bmkp-this-buffer-lighted-alist-only)))
+ (cond ((or (not current-prefix-arg) (consp current-prefix-arg))
+ '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays))
+ ((natnump current-prefix-arg) '(bmkp-autonamed-overlays))
+ (current-prefix-arg '(bmkp-non-autonamed-overlays)))
+ 'MSG))
+ (unless overlays-symbols
+ (setq overlays-symbols '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays)))
+ (let ((bmkp-use-region nil) ; Inhibit region handling.
+ (total 0)
+ (nb-auto 0)
+ (nb-non-auto 0)
+ (new-auto 0)
+ (new-non-auto 0)
+ (nb-lit (bmkp-number-lighted))
+ bmk bmk-name autonamedp face style pos buf bmk-ov passes-when-p)
+ (catch 'bmkp-light-bookmarks
+ (dolist (bookmark alist)
+ (setq bmk (bmkp-get-bookmark bookmark 'NOERROR) ; Should be a no-op.
+ bmk-name (and bmk (bmkp-bookmark-name-from-record bmk))
+ autonamedp (and bmk (bmkp-autonamed-bookmark-p bmk-name))
+ face (and bmk (bmkp-light-face bmk))
+ style (and bmk (bmkp-light-style bmk))
+ bmk-ov (bmkp-overlay-of-bookmark bmk)
+ passes-when-p (and bmk (or bmk-ov ; Always highlight if already highlighted.
+ (bmkp-light-when bmk))))
+ (when (and bmk passes-when-p) ; Skip bad bookmark and respect `:when' (unless highlighted).
+ (setq pos (bookmark-get-position bmk)
+ buf (bmkp-get-buffer-name bmk))
+ (save-excursion
+ ;; An alternative here would be to call the handler and let it do the highlighting.
+ ;; In that case, we would need at least to bind the display function to nil while
+ ;; handling, so we don't also do the jump. In particular, we don't want to pop to
+ ;; the bookmark in a new window or frame.
+ ;; Calling the handler would be good for some cases, such as Info, where the
+ ;; highlighting is not really specific to the buffer but to a narrowed part of it.
+ ;;
+ ;; (let ((bmkp-jump-display-function nil)) (bookmark-handle-bookmark bmk))
+ ;;
+ ;; But calling the handler is in general the wrong thing. We don't want highlighting
+ ;; all Dired bookmarks in a given directory to also do all the file marking and
+ ;; subdir hiding associated with each of the bookmarks. So we do just the
+ ;; highlighting, no handling, putting the code in side `with-current-buffer'.
+ (with-current-buffer (or (and buf (get-buffer buf))
+ (current-buffer))
+ (when (and pos (< pos (point-max)))
+ (dolist (ov-symb overlays-symbols)
+ (when (or (and (eq 'bmkp-autonamed-overlays ov-symb) autonamedp)
+ (and (eq 'bmkp-non-autonamed-overlays ov-symb) (not autonamedp)))
+ (let ((ov (bmkp-make/move-overlay-of-style style pos autonamedp bmk bmk-ov)))
+ (when ov ; nil means `none' style.
+ (add-to-list ov-symb ov)
+ (when (eq 'bmkp-autonamed-overlays ov-symb)
+ (unless bmk-ov (setq new-auto (1+ new-auto)))
+ (setq nb-auto (1+ nb-auto)))
+ (when (eq 'bmkp-non-autonamed-overlays ov-symb)
+ (unless bmk-ov (setq new-non-auto (1+ new-non-auto)))
+ (setq nb-non-auto (1+ nb-non-auto)))
+ (when (and (not bmk-ov) (> (setq nb-lit (1+ nb-lit)) bmkp-light-threshold))
+ (setq nb-lit (1- nb-lit))
+ (throw 'bmkp-light-bookmarks bmk))
+ (setq total (1+ total))
+ (overlay-put ov 'priority ; > ediff's 100+, < isearch-overlay's 1001.
+ (or (cdr (assoc ov-symb bmkp-light-priorities))
+ (apply #'min (mapcar #'cdr bmkp-light-priorities))))
+ (unless (memq style '(lfringe rfringe none)) (overlay-put ov 'face face))
+ (overlay-put ov 'evaporate t)
+ (overlay-put ov 'category 'bookmark-plus)
+ (overlay-put ov 'bookmark bmk))))))))))) ; Use full bookmark - name can change.
+ (when msgp (message "%s New: %d auto + %d other, Total: %d auto + %d other = %d"
+ (if (consp current-prefix-arg)
+ (if (> (prefix-numeric-value current-prefix-arg) 4)
+ "[Navlist]"
+ "[All buffers]")
+ "[This buffer]")
+ new-auto new-non-auto nb-auto nb-non-auto total))))
+
+;;;###autoload (autoload 'bmkp-light-navlist-bookmarks "bookmark+")
+(defun bmkp-light-navlist-bookmarks (&optional overlays-symbols msgp) ; Not bound
+ "Highlight bookmarks in the navigation list.
+No prefix arg: all bookmarks.
+Prefix arg >= 0: autonamed bookmarks only.
+Prefix arg < 0: non-autonamed bookmarks only."
+ (interactive
+ (list (cond ((not current-prefix-arg) '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays))
+ ((natnump (prefix-numeric-value current-prefix-arg)) '(bmkp-autonamed-overlays))
+ (current-prefix-arg '(bmkp-non-autonamed-overlays)))
+ 'MSG))
+ (bmkp-light-bookmarks bmkp-nav-alist overlays-symbols msgp))
+
+;;;###autoload (autoload 'bmkp-light-this-buffer "bookmark+")
+(defun bmkp-light-this-buffer (&optional overlays-symbols msgp) ; Not bound
+ "Highlight bookmarks in the current buffer.
+No prefix arg: all bookmarks.
+Prefix arg >= 0: autonamed bookmarks only.
+Prefix arg < 0: non-autonamed bookmarks only."
+ (interactive
+ (list (cond ((not current-prefix-arg) '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays))
+ ((natnump (prefix-numeric-value current-prefix-arg)) '(bmkp-autonamed-overlays))
+ (current-prefix-arg '(bmkp-non-autonamed-overlays)))
+ 'MSG))
+ (bmkp-light-bookmarks (bmkp-this-buffer-alist-only) overlays-symbols msgp))
+
+;;;###autoload (autoload 'bmkp-light-bookmarks-in-region "bookmark+")
+(defun bmkp-light-bookmarks-in-region (start end &optional overlays-symbols msgp) ; Not bound
+ "Highlight bookmarks in the region.
+No prefix arg: all bookmarks.
+Prefix arg >= 0: autonamed bookmarks only.
+Prefix arg < 0: non-autonamed bookmarks only."
+ (interactive
+ (list (region-beginning)
+ (region-end)
+ (cond ((not current-prefix-arg) '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays))
+ ((natnump (prefix-numeric-value current-prefix-arg)) '(bmkp-autonamed-overlays))
+ (current-prefix-arg '(bmkp-non-autonamed-overlays)))
+ 'MSG))
+ (bmkp-light-bookmarks (bmkp-remove-if-not (lambda (bmk) (let ((pos (bookmark-get-position bmk)))
+ (and (>= pos start) (<= pos end))))
+ (bmkp-this-buffer-alist-only))
+ overlays-symbols msgp))
+
+;;;###autoload (autoload 'bmkp-light-autonamed-this-buffer "bookmark+")
+(defun bmkp-light-autonamed-this-buffer (&optional msgp) ; Not bound
+ "Highlight all autonamed bookmarks."
+ (interactive (list 'MSG))
+ (bmkp-light-bookmarks (bmkp-autonamed-this-buffer-alist-only) '(bmkp-autonamed-overlays) msgp))
+
+;;;###autoload (autoload 'bmkp-light-non-autonamed-this-buffer "bookmark+")
+(defun bmkp-light-non-autonamed-this-buffer (&optional msgp) ; Not bound
+ "Highlight all non-autonamed bookmarks."
+ (interactive (list 'MSG))
+ (bmkp-light-bookmarks (bmkp-remove-if #'bmkp-autonamed-bookmark-p (bmkp-this-buffer-alist-only))
+ '(bmkp-non-autonamed-overlays) msgp))
+
+;;;###autoload (autoload 'bmkp-cycle-lighted-this-buffer "bookmark+")
+(defun bmkp-cycle-lighted-this-buffer (increment &optional other-window startoverp) ; Not bound
+ "Cycle through highlighted bookmarks in this buffer by INCREMENT.
+Positive INCREMENT cycles forward. Negative INCREMENT cycles backward.
+Interactively, the prefix arg determines INCREMENT:
+ Plain `C-u': 1
+ otherwise: the numeric prefix arg value
+
+To change the sort order, you can filter the `*Bookmark List*' to show
+only highlighted bookmarks for this buffer, sort the bookmarks there,
+and use `\\[bmkp-choose-navlist-from-bookmark-list]', choosing `CURRENT *Bookmark List*' as the
+navigation list.
+
+Then you can cycle the bookmarks using `bookmark-cycle'
+\(`\\[bmkp-next-bookmark-repeat]' etc.), instead of `bookmark-cycle-lighted-this-buffer'.
+
+In Lisp code:
+ Non-nil OTHER-WINDOW means jump to the bookmark in another window.
+ Non-nil STARTOVERP means reset `bmkp-current-nav-bookmark' to the
+ first bookmark in the navlist."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) nil startovr)))
+ (bookmark-maybe-load-default-file)
+ (let ((bmkp-sort-comparer bmkp-this-file/buffer-cycle-sort-comparer))
+ (setq bmkp-nav-alist (bmkp-sort-omit (bmkp-this-buffer-lighted-alist-only))))
+ (unless bmkp-nav-alist (error "No lighted bookmarks for cycling"))
+ (unless (and bmkp-current-nav-bookmark
+ (not startoverp)
+ (bmkp-get-bookmark bmkp-current-nav-bookmark 'NOERROR)
+ (bmkp-this-buffer-p bmkp-current-nav-bookmark)) ; Exclude desktops etc.
+ (setq bmkp-current-nav-bookmark (car bmkp-nav-alist)))
+ (if (bmkp-cycle-1 increment other-window startoverp)
+ (unless (or (bmkp-sequence-bookmark-p bmkp-current-nav-bookmark)
+ (bmkp-function-bookmark-p bmkp-current-nav-bookmark))
+ (message "Position: %9d, Bookmark: `%s'" (point) (bmkp-bookmark-name-from-record
+ bmkp-current-nav-bookmark)))
+ (message "Invalid bookmark: `%s'" (bmkp-bookmark-name-from-record bmkp-current-nav-bookmark))))
+
+;;;###autoload (autoload 'bmkp-cycle-lighted-this-buffer-other-window "bookmark+")
+(defun bmkp-cycle-lighted-this-buffer-other-window (increment &optional startoverp) ; Not bound
+ "Same as `bmkp-cycle-lighted-this-buffer' but uses another window."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-lighted-this-buffer increment 'OTHER-WINDOW startoverp))
+
+;;;###autoload (autoload 'bmkp-next-lighted-this-buffer "bookmark+")
+(defun bmkp-next-lighted-this-buffer (n &optional startoverp) ; Repeatable key (e.g. `S-f2'), not bound
+ "Jump to the Nth-next highlighted bookmark in the current buffer.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one.
+See also `bmkp-cycle-lighted-this-buffer'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-lighted-this-buffer n nil startoverp))
+
+;;;###autoload (autoload 'bmkp-previous-lighted-this-buffer "bookmark+")
+(defun bmkp-previous-lighted-this-buffer (n &optional startoverp) ; Repeatable key (e.g. `f2'), not bound
+ "Jump to the Nth-previous highlighted bookmark in the current buffer.
+See `bmkp-next-lighted-this-buffer'."
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (bmkp-cycle-lighted-this-buffer (- n) nil startoverp))
+
+;;;###autoload (autoload 'bmkp-next-lighted-this-buffer-repeat "bookmark+")
+(defun bmkp-next-lighted-this-buffer-repeat (arg) ; `C-x p C-down'
+ "Jump to the Nth next highlighted bookmark in the current buffer.
+This is a repeatable version of `bmkp-next-bookmark-this-buffer'.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one (and no repeat)."
+ (interactive "P")
+ (require 'repeat)
+ (bmkp-repeat-command 'bmkp-next-lighted-this-buffer))
+
+;;;###autoload (autoload 'bmkp-previous-lighted-this-buffer-repeat "bookmark+")
+(defun bmkp-previous-lighted-this-buffer-repeat (arg) ; `C-x p C-up'
+ "Jump to the Nth previous highlighted bookmark in the current buffer.
+See `bmkp-next-lighted-this-buffer-repeat'."
+ (interactive "P")
+ (require 'repeat)
+ (bmkp-repeat-command 'bmkp-previous-lighted-this-buffer))
+
+;;;###autoload (autoload 'bmkp-describe-bookmark-lighted-here "bookmark+")
+(defun bmkp-describe-bookmark-lighted-here (&optional position defn) ; `C-x p ?'
+ "Describe a highlighted bookmark at point or the same line.
+If there is more than one highlighted bookmark present then which one
+is described is undefined. When multiple highlighted bookmarks are
+present you might want to use `\\[bmkp-bookmarks-lighted-at-point]' to see the names of all of the
+bookmarks at point, and then use `\\[bmkp-describe-bookmark]' to describe one of them.
+
+When called from Lisp:
+ * Use POSITION, not point.
+ * DEFN corresponds to the prefix arg: non-nil means show show the
+ internal definition of the bookmark."
+ (interactive (list (point) current-prefix-arg))
+ (let ((bmk (or (bmkp-a-bookmark-lighted-at-pos position 'FULL)
+ (bmkp-a-bookmark-lighted-on-this-line 'FULL))))
+ (unless bmk (error "No highlighted bookmark on this line"))
+ (bmkp-describe-bookmark bmk defn)))
+
+
+;;(@* "Other Functions")
+;; *** Other Functions ***
+
+(defun bmkp-light-face (bookmark)
+ "Return the face to use to highlight BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+Returns:
+ nil if BOOKMARK is not a valid bookmark;
+ the `:face', if any, specified by BOOKMARK's `lighting' entry;
+ `bmkp-light-autonamed-region' if an autonamed region bookmark;
+ `bmkp-light-non-autonamed-region' if a non-autonamed region bookmark;
+ `bmkp-light-autonamed' if an autonamed non-region bookmark;
+ `bmkp-light-non-autonamed' otherwise."
+ (setq bookmark (bmkp-get-bookmark bookmark 'NOERROR))
+ (or (bmkp-lighting-face bookmark)
+ (and bookmark (if (bmkp-region-bookmark-p bookmark)
+ (if (bmkp-autonamed-bookmark-p bookmark)
+ 'bmkp-light-autonamed-region
+ 'bmkp-light-non-autonamed-region)
+ (if (bmkp-autonamed-bookmark-p bookmark)
+ 'bmkp-light-autonamed
+ 'bmkp-light-non-autonamed)))))
+
+(defun bmkp-light-style (bookmark)
+ "Return the style to use to highlight BOOKMARK.
+BOOKMARK is a bookmark name or a bookmark record.
+Returns:
+ * nil if BOOKMARK is not a valid bookmark;
+ * the `:style', if any, specified by BOOKMARK's `lighting' entry;
+ * the value of `bmkp-light-style-autonamed-region' if autonamed and
+ recording a region
+ * the value of `bmkp-light-style-non-autonamed-region' if autonamed
+ and recording a region
+ * the value of `bmkp-light-style-autonamed' if autonamed and not
+ recording a region
+ * the value of `bmkp-light-style-non-autonamed-region' if autonamed
+ and not recording a region"
+ (setq bookmark (bmkp-get-bookmark bookmark 'NOERROR))
+ (or (bmkp-lighting-style bookmark)
+ (and bookmark (if (bmkp-region-bookmark-p bookmark)
+ (if (bmkp-autonamed-bookmark-p bookmark)
+ bmkp-light-style-autonamed-region
+ bmkp-light-style-non-autonamed-region)
+ (if (bmkp-autonamed-bookmark-p bookmark)
+ bmkp-light-style-autonamed
+ bmkp-light-style-non-autonamed)))))
+
+(defun bmkp-light-when (bookmark)
+ "Return non-nil if BOOKMARK should be highlighted.
+BOOKMARK's `:when' condition is used to determine this.
+BOOKMARK is a bookmark name or a bookmark record."
+ (setq bookmark (bmkp-get-bookmark bookmark 'NOERROR))
+ (let ((this-bookmark bookmark)
+ (this-bookmark-name (bmkp-bookmark-name-from-record bookmark))
+ (when-sexp (bmkp-lighting-when bookmark)))
+ (not (eq :no-light (eval when-sexp)))))
+
+(defun bmkp-lighting-face (bookmark)
+ "`:face' specified by BOOKMARK's `lighting', or nil if no `:face' entry.
+BOOKMARK is a bookmark name or a bookmark record.
+
+The `:face' entry is the face (a symbol) used to highlight BOOKMARK.
+Alternatively, it can be `auto' or nil, which both mean the same as
+having no `:face' entry: do not override automatic face choice."
+ (bmkp-lighting-attribute bookmark :face))
+
+(defun bmkp-lighting-style (bookmark)
+ "`:style' specified by BOOKMARK's `lighting', or nil if no `:style' entry.
+BOOKMARK is a bookmark name or a bookmark record.
+
+The `:style' entry is the style used to highlight BOOKMARK.
+It is a value acceptable for `bmkp-light-style-non-autonamed'.
+Alternatively, it can be `auto' or nil, which both mean the same as
+having no `:style' entry: do not override automatic style choice."
+ (bmkp-lighting-attribute bookmark :style))
+
+(defun bmkp-lighting-when (bookmark)
+ "`:when' specified by BOOKMARK's `lighting', or nil if no `:when' entry.
+BOOKMARK is a bookmark name or a bookmark record.
+
+The `:when' entry is a sexp that is eval'd when you try to highlight
+BOOKMARK. If the result is the symbol `:no-light', then do not
+highlight. Otherwise, highlight. (Note that highlighting happens if
+the value is nil or there is no `:when' entry.)"
+ (bmkp-lighting-attribute bookmark :when))
+
+(defun bmkp-lighting-attribute (bookmark attribute)
+ "ATTRIBUTE specified by BOOKMARK's `lighting', or nil if no such attribute.
+BOOKMARK is a bookmark name or a bookmark record.
+ATTRIBUTE is `:style' or `:face'."
+ (setq bookmark (bmkp-get-bookmark bookmark 'NOERROR))
+ (let* ((lighting (and bookmark (bmkp-get-lighting bookmark)))
+ (attr (and (consp lighting) (plist-get lighting attribute))))
+ (when (and (eq 'auto attr) (not (eq :when attribute)))
+ (setq attr nil))
+ attr))
+
+(defun bmkp-get-lighting (bookmark)
+ "Return the `lighting' property list for BOOKMARK.
+This is the cdr of the `lighting' entry (i.e. the rest of the entry,
+ with `lighting' removed).
+BOOKMARK is a bookmark name or a bookmark record."
+ (bookmark-prop-get bookmark 'lighting))
+
+(defun bmkp-bookmark-overlay-p (overlay)
+ "Return non-nil if OVERLAY is a bookmark overlay.
+The non-nil value returned is in fact the full bookmark."
+ (and (overlayp overlay) (overlay-get overlay 'bookmark)))
+
+(defun bmkp-default-lighted ()
+ "Return a highlighted bookmark at point or on this line, or nil if none.
+For Emacs 23+, if there is a highlighted bookmark at point, return a
+ list of all such."
+ (or (if (> emacs-major-version 22) (bmkp-bookmarks-lighted-at-point) (bmkp-a-bookmark-lighted-at-pos))
+ (bmkp-a-bookmark-lighted-on-this-line)))
+
+(defun bmkp-a-bookmark-lighted-on-this-line (&optional fullp msgp)
+ "Return a bookmark highlighted on the current line or nil if none.
+The search for a highlighted bookmark moves left to bol from point,
+ then right to eol from point.
+Return the bookmark name or, if FULLP non-nil, the full bookmark data."
+ (let ((pos (point))
+ (bol (1+ (line-beginning-position)))
+ (eol (1- (line-end-position)))
+ bmk)
+ (catch 'bmkp-a-bookmark-lighted-on-this-line
+ (while (>= pos bol)
+ (when (setq bmk (bmkp-a-bookmark-lighted-at-pos pos))
+ (throw 'bmkp-a-bookmark-lighted-on-this-line bmk))
+ (setq pos (1- pos)))
+ (while (<= pos eol)
+ (when (setq bmk (bmkp-a-bookmark-lighted-at-pos pos))
+ (throw 'bmkp-a-bookmark-lighted-on-this-line bmk))
+ (setq pos (1+ pos)))
+ nil)
+ (when (and bmk fullp) (setq bmk (bmkp-get-bookmark bmk)))
+ bmk))
+
+(defun bmkp-a-bookmark-lighted-at-pos (&optional position fullp)
+ "Return a bookmark (in current bookmark list) highlighted at POSITION.
+Return nil if there is none such.
+POSITION defaults to point.
+Return the bookmark name or, if FULLP non-nil, the full bookmark data."
+ (unless position (setq position (point)))
+ (let (bmk)
+ (catch 'bmkp-a-bookmark-lighted-at-pos
+ (dolist (ov (overlays-at position))
+ (when (setq bmk (overlay-get ov 'bookmark))
+ (throw 'bmkp-a-bookmark-lighted-at-pos bmk)))
+ nil)
+ (let ((b-in-list (bmkp-get-bookmark-in-alist bmk 'NOERROR)))
+ (and b-in-list ; Must be in current bookmark list.
+ (if fullp b-in-list (bmkp-bookmark-name-from-record bmk))))))
+
+(defun bmkp-read-set-lighting-args (&optional default-style default-face default-when)
+ "Read args STYLE, FACE, and WHEN for commands that set `lighting' prop.
+Optional args are the default values (strings) for reading new values."
+ (let* ((icicle-unpropertize-completion-result-flag t)
+ (style (cdr (assoc (let ((completion-ignore-case t))
+ (completing-read "Style: " bmkp-light-styles-alist
+ nil t nil nil default-style))
+ bmkp-light-styles-alist)))
+ (face (and (not (member style '(lfringe rfringe none))) ; No face possible for these.
+ (y-or-n-p "Change face? ") ; Allow nil, for `auto'.
+ (condition-case nil ; Emacs 22+ accepts a default.
+ (read-face-name "Face: " default-face)
+ (wrong-number-of-arguments (read-face-name "Face: ")))))
+ (when-cands `(("auto" . nil)
+ ("conditionally (read sexp)")
+ ("never" . :no-light)))
+ (when (completing-read "When: " when-cands nil t nil nil
+ (if default-when "conditionally (read sexp)" "auto")))
+ (evald (if (bmkp-string-match-p "^con" when)
+ (read-from-minibuffer "Highlight when (sexp): " nil
+ (if (boundp 'pp-read-expression-map)
+ pp-read-expression-map
+ read-expression-map)
+ t 'read-expression-history default-when)
+ (cdr (assoc when when-cands)))))
+ (list style face evald)))
+
+(defun bmkp-lighted-alist-only ()
+ "`bookmark-alist', with only highlighted bookmarks.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lambda (bmk) (bmkp-lighted-p bmk)) bookmark-alist))
+
+(defun bmkp-this-buffer-lighted-alist-only ()
+ "`bookmark-alist', with only highlighted bookmarks for the current buffer.
+A new list is returned (no side effects)."
+ (bookmark-maybe-load-default-file)
+ (bmkp-remove-if-not (lambda (bmk) (and (bmkp-this-buffer-p bmk) (bmkp-lighted-p bmk)))
+ bookmark-alist))
+
+(defun bmkp-number-lighted (&optional overlays-symbols)
+ "Number of bookmarks highlighted."
+ (unless overlays-symbols
+ (setq overlays-symbols '(bmkp-autonamed-overlays bmkp-non-autonamed-overlays)))
+ (let ((count 0))
+ (dolist (ov-symb overlays-symbols)
+ (dolist (ov (symbol-value ov-symb)) (when (overlay-buffer ov) (setq count (1+ count)))))
+ count))
+
+(defalias 'bmkp-lighted-p 'bmkp-overlay-of-bookmark)
+(defun bmkp-overlay-of-bookmark (bookmark &optional overlays)
+ "Return the overlay for BOOKMARK in OVERLAYS, or nil if none.
+BOOKMARK is a bookmark name or a bookmark record.
+Optional arg OVERLAYS is the list of overlays to check.
+If nil, check overlays for both autonamed and non-autonamed bookmarks."
+ (setq bookmark (bmkp-get-bookmark bookmark 'NOERROR))
+ (and bookmark ; Return nil for no such bookmark.
+ (catch 'bmkp-overlay-of-bookmark
+ (dolist (ov (if overlays
+ (apply #'append (mapcar #'symbol-value overlays))
+ (append bmkp-autonamed-overlays bmkp-non-autonamed-overlays)))
+ (when (and (overlay-buffer ov) (eq bookmark (overlay-get ov 'bookmark)))
+ (throw 'bmkp-overlay-of-bookmark ov)))
+ nil)))
+
+(defun bmkp-make/move-overlay-of-style (style pos autonamedp bookmark &optional overlay)
+ "Return a bookmark overlay of STYLE at position POS for BOOKMARK.
+AUTONAMEDP non-nil means the bookmark is autonamed.
+Regardless of STYLE, set `help-echo' to the bookmark description.
+If OVERLAY is non-nil:
+ Then it is the overlay to use - change to STYLE and return overlay.
+ Otherwise, create a new overlay and return it.
+If STYLE is `none' then:
+ If OVERLAY is non-nil, delete it and return nil."
+ (let ((ov overlay))
+ (when (and (< emacs-major-version 22) (not (rassq style bmkp-light-styles-alist)))
+ (message "Fringe styles not supported before Emacs 22 - changing to `line' style")
+ (setq style 'line))
+ (case style
+ (region (and (bmkp-region-bookmark-p bookmark)
+ (let ((end (bmkp-get-end-position bookmark)))
+ (if (not ov)
+ (setq ov (make-overlay pos end nil 'FRONT-ADVANCE))
+ (move-overlay ov pos end)))))
+ (line (if (not ov)
+ (setq ov (save-excursion
+ (make-overlay
+ (progn (goto-char pos) (line-beginning-position 1))
+ (progn (goto-char pos) (line-beginning-position 2))
+ nil
+ 'FRONT-ADVANCE)))
+ (overlay-put ov 'before-string nil) ; Remove any fringe highlighting.
+ (save-excursion
+ (move-overlay ov
+ (progn (goto-char pos) (line-beginning-position 1))
+ (progn (goto-char pos) (line-beginning-position 2))))))
+ (lfringe (setq ov (bmkp-make/move-fringe 'left pos autonamedp ov)))
+ (rfringe (setq ov (bmkp-make/move-fringe 'right pos autonamedp ov)))
+ (line+lfringe (setq ov (bmkp-make/move-fringe 'left pos autonamedp ov 'LINEP)))
+ (line+rfringe (setq ov (bmkp-make/move-fringe 'right pos autonamedp ov 'LINEP)))
+ (bol (if (not ov)
+ (setq ov (save-excursion (goto-char pos)
+ (make-overlay (line-beginning-position)
+ (1+ (line-beginning-position))
+ nil
+ 'FRONT-ADVANCE)))
+ (overlay-put ov 'before-string nil) ; Remove any fringe highlighting.
+ (save-excursion (goto-char pos)
+ (move-overlay ov (line-beginning-position)
+ (1+ (line-beginning-position))))))
+ (point (if (not ov)
+ (setq ov (make-overlay pos (1+ pos) nil 'FRONT-ADVANCE))
+ (overlay-put ov 'before-string nil) ; Remove any fringe highlighting.
+ (move-overlay ov pos (1+ pos))))
+ (none (when ov (delete-overlay ov)) (setq ov nil)))
+
+ ;; Emacs bug # prevents making use of a face in a `help-echo' tooltip.
+ ;; (when ov (overlay-put ov 'help-echo (bmkp-propertize (funcall bmkp-tooltip-content-function bookmark)
+ ;; 'face 'bmkp-tooltip-content-face)))
+ (when ov (overlay-put ov 'help-echo (funcall bmkp-tooltip-content-function bookmark)))
+ ov))
+
+;; Not used for Emacs 20-21.
+(defun bmkp-make/move-fringe (side pos autonamedp &optional overlay linep)
+ "Return an overlay that uses the fringe.
+If SIDE is `right' then use the right fringe, otherwise left.
+POS is the overlay position.
+AUTONAMEDP: non-nil means use face `bmkp-light-fringe-autonamed'.
+ nil means use face `bmkp-light-fringe-non-autonamed'.
+If OVERLAY is non-nil it is the overlay to use.
+ Otherwise, create a new overlay.
+Non-nil LINEP means also highlight the line containing POS."
+ (unless (> emacs-major-version 21) (error "Fringe styles not supported before Emacs 22"))
+ (let ((ov overlay))
+ (if ov
+ (save-excursion (move-overlay overlay (progn (goto-char pos)
+ (goto-char (line-beginning-position)))
+ (1+ (point))))
+ (setq ov (save-excursion (make-overlay (progn (goto-char pos)
+ (goto-char (line-beginning-position)))
+ (1+ (point))
+ nil
+ 'FRONT-ADVANCE))))
+ (overlay-put ov 'before-string (bmkp-fringe-string side autonamedp))
+ (if linep
+ (move-overlay ov (save-excursion (goto-char pos) (line-beginning-position 1))
+ (save-excursion (goto-char pos) (line-beginning-position 2)))
+ (overlay-put ov 'face nil)) ; Remove any non-fringe highlighting.
+ ov))
+
+;; Not used for Emacs 20-21.
+(defun bmkp-fringe-string (side autonamedp)
+ "Return a fringe string for a bookmark overlay.
+If SIDE is `right' then use the right fringe, otherwise left.
+AUTONAMEDP: non-nil means use face `bmkp-light-fringe-autonamed'.
+ nil means use face `bmkp-light-fringe-non-autonamed'."
+ (unless (> emacs-major-version 21) (error "Fringe styles not supported before Emacs 22"))
+ (let ((fringe-string (copy-sequence (if autonamedp "*AUTO*" "*NONAUTO*"))))
+ (put-text-property 0 (length fringe-string)
+ 'display (if (eq side 'right)
+ (list 'right-fringe
+ bmkp-light-right-fringe-bitmap
+ (if autonamedp
+ 'bmkp-light-fringe-autonamed
+ 'bmkp-light-fringe-non-autonamed))
+ (list 'left-fringe
+ bmkp-light-left-fringe-bitmap
+ (if autonamedp
+ 'bmkp-light-fringe-autonamed
+ 'bmkp-light-fringe-non-autonamed)))
+ fringe-string)
+ fringe-string))
+
+;; This is also in `bookmark+-bmu.el', since `bookmark+-lit.el' is loaded first but is optional.
+;;
+(if (fboundp 'pop-to-buffer-same-window)
+ (defalias 'bmkp--pop-to-buffer-same-window 'pop-to-buffer-same-window)
+ (defalias 'bmkp--pop-to-buffer-same-window 'switch-to-buffer))
+
+
+;;;;;;;;;;;;;;;;;;;
+
+(provide 'bookmark+-lit)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; bookmark+-lit.el ends here
--- /dev/null
+;;; bookmark+-mac.el --- Macros for Bookmark+.
+;;
+;; Filename: bookmark+-mac.el
+;; Description: Macros for Bookmark+.
+;; Author: Drew Adams
+;; Maintainer: Drew Adams
+;; Copyright (C) 2000-2022, Drew Adams, all rights reserved.
+;; Created: Sun Aug 15 11:12:30 2010 (-0700)
+;; Last-Updated: Fri Jan 14 12:34:20 2022 (-0800)
+;; By: dradams
+;; Update #: 223
+;; URL: https://www.emacswiki.org/emacs/download/bookmark%2b-mac.el
+;; Doc URL: https://www.emacswiki.org/emacs/BookmarkPlus
+;; Keywords: bookmarks, bookmark+, placeholders, annotations, search, info, url, eww, w3m, gnus
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x, 26.x
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Macros for Bookmark+.
+;;
+;; The Bookmark+ libraries are these:
+;;
+;; `bookmark+.el' - main (driver) library
+;; `bookmark+-mac.el' - Lisp macros (this file)
+;; `bookmark+-bmu.el' - code for the `*Bookmark List*' (bmenu)
+;; `bookmark+-1.el' - other (non-bmenu) required code
+;; `bookmark+-lit.el' - (optional) code for highlighting bookmarks
+;; `bookmark+-key.el' - key and menu bindings
+;;
+;; `bookmark+-doc.el' - documentation (comment-only file)
+;; `bookmark+-chg.el' - change log (comment-only file)
+;;
+;; The documentation (in `bookmark+-doc.el') includes how to
+;; byte-compile and install Bookmark+. The documentation is also
+;; available in these ways:
+;;
+;; 1. From the bookmark list (`C-x r l'):
+;; Use `?' to show the current bookmark-list status and general
+;; help, then click link `Doc in Commentary' or link `Doc on the
+;; Web'.
+;;
+;; 2. From the Emacs-Wiki Web site:
+;; https://www.emacswiki.org/emacs/BookmarkPlus.
+;;
+;; 3. From the Bookmark+ group customization buffer:
+;; `M-x customize-group bookmark-plus', then click link
+;; `Commentary'.
+;;
+;; (The commentary links in #1 and #3 work only if you have library
+;; `bookmark+-doc.el' in your `load-path'.)
+;;
+;;
+;; ****** NOTE ******
+;;
+;; WHENEVER you update Bookmark+ (i.e., download new versions of
+;; Bookmark+ source files), I recommend that you do the
+;; following:
+;;
+;; 1. Delete ALL existing BYTE-COMPILED Bookmark+ files
+;; (bookmark+*.elc).
+;; 2. Load Bookmark+ (`load-library' or `require').
+;; 3. Byte-compile the source files.
+;;
+;; In particular, ALWAYS LOAD `bookmark+-mac.el' (not
+;; `bookmark+-mac.elc') BEFORE YOU BYTE-COMPILE new versions of
+;; the files, in case there have been any changes to Lisp macros
+;; (in `bookmark+-mac.el').
+;;
+;; (This is standard procedure for Lisp: code that depends on
+;; macros needs to be byte-compiled anew after loading the
+;; updated macros.)
+;;
+;; ******************
+
+;;(@> "Index")
+;;
+;; If you have library `linkd.el' and Emacs 22 or later, load
+;; `linkd.el' and turn on `linkd-mode' now. It lets you easily
+;; navigate around the sections of this doc. Linkd mode will
+;; highlight this Index, as well as the cross-references and section
+;; headings throughout this file. You can get `linkd.el' here:
+;; https://www.emacswiki.org/emacs/download/linkd.el.
+;;
+;; (@> "Things Defined Here")
+;; (@> "Functions")
+;; (@> "Macros")
+
+;;(@* "Things Defined Here")
+;;
+;; Things Defined Here
+;; -------------------
+;;
+;; Macros defined here:
+;;
+;; `bmkp-define-cycle-command', `bmkp-define-history-variables',
+;; `bmkp-define-next+prev-cycle-commands',
+;; `bmkp-define-show-only-command', `bmkp-define-sort-command',
+;; `bmkp-define-file-sort-predicate', `bmkp-menu-bar-make-toggle',
+;; `bmkp-with-bookmark-dir', `bmkp-with-help-window',
+;; `bmkp-with-output-to-plain-temp-buffer'.
+;;
+;; Non-interactive functions defined here:
+;;
+;; `bmkp-bookmark-data-from-record',
+;; `bmkp-bookmark-name-from-record',
+;; `bmkp-replace-regexp-in-string', `bmkp-types-alist',
+;; `bookmark-name-from-full-record', `bookmark-name-from-record'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(require 'bookmark)
+;; bookmark-bmenu-bookmark, bookmark-bmenu-ensure-position,
+;; bookmark-bmenu-surreptitiously-rebuild-list, bmkp-get-bookmark,
+;; bookmark-get-filename
+
+
+;;(@* "Functions")
+
+;; Some general Renamings.
+;;
+;; 1. Fix incompatibility introduced by gratuitous Emacs name change.
+;;
+(cond ((and (fboundp 'bookmark-name-from-record) (not (fboundp 'bookmark-name-from-full-record)))
+ (defalias 'bookmark-name-from-full-record 'bookmark-name-from-record))
+ ((and (fboundp 'bookmark-name-from-full-record) (not (fboundp 'bookmark-name-from-record)))
+ (defalias 'bookmark-name-from-record 'bookmark-name-from-full-record)))
+
+;; 2. The vanilla name of the first is misleading, as it returns only the cdr of the record.
+;; The second is for consistency.
+;;
+(defalias 'bmkp-bookmark-data-from-record 'bookmark-get-bookmark-record)
+(defalias 'bmkp-bookmark-name-from-record 'bookmark-name-from-full-record)
+
+
+;; (eval-when-compile (require 'bookmark+-bmu))
+;; bmkp-assoc-delete-all, bmkp-bmenu-barf-if-not-in-menu-list,
+;; bmkp-bmenu-goto-bookmark-named, bmkp-sort-orders-alist
+
+;; (eval-when-compile (require 'bookmark+-1))
+;; bmkp-file-bookmark-p, bmkp-float-time, bmkp-local-file-bookmark-p,
+;; bmkp-msg-about-sort-order, bmkp-reverse-sort-p, bmkp-sort-comparer
+
+
+;;; This is also defined in `bookmark+-bmu.el'. It is used here to produce the code for
+;;; `bmkp-define-show-only-command' and `bmkp-define-sort-command'.
+;;;
+(defun bmkp-replace-regexp-in-string (regexp rep string &optional fixedcase literal subexp start)
+ "Replace all matches for REGEXP with REP in STRING and return STRING."
+ (if (fboundp 'replace-regexp-in-string) ; Emacs > 20.
+ (replace-regexp-in-string regexp rep string fixedcase literal subexp start)
+ (if (string-match regexp string) (replace-match rep nil nil string) string))) ; Emacs 20
+
+;;(@* "Macros")
+
+;;; Macros -----------------------------------------------------------
+
+;; Same as `icicle-with-help-window' in `icicles-mac.el'.
+;;;###autoload (autoload 'bmkp-with-help-window "bookmark+")
+(defmacro bmkp-with-help-window (buffer &rest body)
+ "`with-help-window', if available; else `with-output-to-temp-buffer'."
+ (if (fboundp 'with-help-window)
+ `(with-help-window ,buffer ,@body)
+ `(with-output-to-temp-buffer ,buffer ,@body)))
+
+(put 'bmkp-with-help-window 'common-lisp-indent-function '(4 &body))
+
+
+;;;###autoload (autoload 'bmkp-with-output-to-plain-temp-buffer "bookmark+")
+(defmacro bmkp-with-output-to-plain-temp-buffer (buf &rest body)
+ "Like `with-output-to-temp-buffer', but with no `*Help*' navigation stuff."
+ `(unwind-protect
+ (progn
+ (remove-hook 'temp-buffer-setup-hook 'help-mode-setup)
+ (remove-hook 'temp-buffer-show-hook 'help-mode-finish)
+ (with-output-to-temp-buffer ,buf ,@body))
+ (add-hook 'temp-buffer-setup-hook 'help-mode-setup)
+ (add-hook 'temp-buffer-show-hook 'help-mode-finish)))
+
+(put 'bmkp-with-output-to-plain-temp-buffer 'common-lisp-indent-function '(4 &body))
+
+
+;;;###autoload (autoload 'bmkp-define-cycle-command "bookmark+")
+(defmacro bmkp-define-cycle-command (type &optional otherp)
+ "Define a cycling command for bookmarks of type TYPE.
+Non-nil OTHERP means define a command that cycles in another window."
+ `(defun ,(intern (format "bmkp-cycle-%s%s" type (if otherp "-other-window" "")))
+ (increment &optional startoverp)
+ ,(if otherp
+ (format "Same as `bmkp-cycle-%s', but use other window." type)
+ (format "Cycle through %s bookmarks by INCREMENT (default: 1).
+Positive INCREMENT cycles forward. Negative INCREMENT cycles backward.
+Interactively, the prefix arg determines INCREMENT:
+ Plain `C-u': 1
+ otherwise: the numeric prefix arg value
+
+Plain `C-u' also means start over at first bookmark.
+
+In Lisp code:
+ Non-nil STARTOVERP means reset `bmkp-current-nav-bookmark' to the
+ first bookmark in the navlist." type))
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg))
+ startovr)))
+ (let ((bmkp-nav-alist (bmkp-sort-omit (,(intern (format "bmkp-%s-alist-only" type))))))
+ (bmkp-cycle increment ,otherp startoverp))))
+
+;;;###autoload (autoload 'bmkp-define-next+prev-cycle-commands "bookmark+")
+(defmacro bmkp-define-next+prev-cycle-commands (type &optional otherp)
+ "Define `next' and `previous' commands for bookmarks of type TYPE.
+Non-nil OTHERP means define a command that cycles in another window."
+ `(progn
+ ;; `next' command.
+ (defun ,(intern (format "bmkp-next-%s-bookmark%s" type (if otherp "-other-window" "")))
+ (n &optional startoverp)
+ ,(if otherp
+ (format "Same as `bmkp-next-%s-bookmark', but use other window." type)
+ (format "Jump to the Nth-next %s bookmark.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one.
+See also `bmkp-cycle-%s'." type type))
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (,(intern (format "bmkp-cycle-%s%s" type (if otherp "-other-window" ""))) n startoverp))
+
+ ;; `previous' command.
+ (defun ,(intern (format "bmkp-previous-%s-bookmark%s" type (if otherp "-other-window" "")))
+ (n &optional startoverp)
+ ,(if otherp
+ (format "Same as `bmkp-previous-%s-bookmark', but use other window." type)
+ (format "Jump to the Nth-previous %s bookmark.
+See `bmkp-next-%s-bookmark'." type type))
+ (interactive (let ((startovr (consp current-prefix-arg)))
+ (list (if startovr 1 (prefix-numeric-value current-prefix-arg)) startovr)))
+ (,(intern (format "bmkp-cycle-%s%s" type (if otherp "-other-window" "")))
+ (- n) startoverp))
+
+ ;; `next' repeating command.
+ (defun ,(intern (format "bmkp-next-%s-bookmark%s-repeat"
+ type
+ (if otherp "-other-window" "")))
+ (arg)
+ ,(if otherp
+ (format "Same as `bmkp-next-%s-bookmark-repeat', but use other window." type)
+ (format "Jump to the Nth-next %s bookmark.
+This is a repeatable version of `bmkp-next-%s-bookmark'.
+N defaults to 1, meaning the next one.
+Plain `C-u' means start over at the first one (and no repeat)." type type))
+ (interactive "P")
+ (require 'repeat)
+ (bmkp-repeat-command
+ ',(intern (format "bmkp-next-%s-bookmark%s" type (if otherp "-other-window" "")))))
+
+ ;; `previous repeating command.
+ (defun ,(intern (format "bmkp-previous-%s-bookmark%s-repeat"
+ type
+ (if otherp "-other-window" "")))
+ (arg)
+ ,(if otherp
+ (format "Same as `bmkp-previous-%s-bookmark-repeat', but use other window." type)
+ (format "Jump to the Nth-previous %s bookmark.
+See `bmkp-next-%s-bookmark-repeat'." type type))
+ (interactive "P")
+ (require 'repeat)
+ (bmkp-repeat-command
+ ',(intern (format "bmkp-previous-%s-bookmark%s" type (if otherp "-other-window" "")))))))
+
+;; We don't bother making this hygienic. Presumably only the Bookmark+ code will call it.
+;;;###autoload (autoload 'bmkp-define-show-only-command "bookmark+")
+(defmacro bmkp-define-show-only-command (type doc-string filter-function)
+ "Define a command to show only bookmarks of TYPE in *Bookmark List*.
+TYPE is a short string or symbol describing the type of bookmarks.
+
+The new command is named `bmkp-bmenu-show-only-TYPED-bookmarks', where
+TYPED is TYPE, but with any spaces replaced by hyphens (`-').
+Example: `bmkp-bmenu-show-only-tagged-bookmarks', for TYPE `tagged'.
+
+DOC-STRING is the doc string of the new command.
+
+The command shows only the bookmarks allowed by FILTER-FUNCTION.
+
+In case of error, variables `bmkp-bmenu-filter-function',
+`bmkp-bmenu-title', and `bmkp-latest-bookmark-alist' are reset to
+their values before the command was invoked."
+ (unless (stringp type) (setq type (symbol-name type)))
+ (let* ((type-- (bmkp-replace-regexp-in-string "\\s-+" "-" type))
+ (command (intern (format "bmkp-bmenu-show-only-%s-bookmarks" type--))))
+ `(progn
+ (defun ,command ()
+ ,doc-string
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (let ((orig-filter-fn bmkp-bmenu-filter-function)
+ (orig-title bmkp-bmenu-title)
+ (orig-latest-alist bmkp-latest-bookmark-alist))
+ (condition-case err
+ (progn (setq bmkp-bmenu-filter-function ',filter-function
+ bmkp-bmenu-title ,(format "%s Bookmarks" (capitalize type)))
+ (let ((bookmark-alist (funcall bmkp-bmenu-filter-function)))
+ (setq bmkp-latest-bookmark-alist bookmark-alist)
+ (bookmark-bmenu-list 'filteredp))
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order (bmkp-current-sort-order)
+ ,(format "Only %s bookmarks are shown" type))))
+ (error (progn (setq bmkp-bmenu-filter-function orig-filter-fn
+ bmkp-bmenu-title orig-title
+ bmkp-latest-bookmark-alist orig-latest-alist)
+ (error "%s" (error-message-string err))))))))))
+
+;;;###autoload (autoload 'bmkp-define-sort-command "bookmark+")
+(defmacro bmkp-define-sort-command (sort-order comparer doc-string)
+ "Define a command to sort bookmarks in the bookmark list by SORT-ORDER.
+SORT-ORDER is a short string or symbol describing the sorting method.
+Examples: \"by last access time\", \"by bookmark name\".
+
+The new command is named by replacing any spaces in SORT-ORDER with
+hyphens (`-') and then adding the prefix `bmkp-bmenu-sort-'. Example:
+`bmkp-bmenu-sort-by-bookmark-name', for SORT-ORDER `by bookmark name'.
+
+COMPARER compares two bookmarks, returning non-nil if and only if the
+first bookmark sorts before the second. It must be acceptable as a
+value of `bmkp-sort-comparer'. That is, it is either nil, a
+predicate, or a list ((PRED...) FINAL-PRED). See the doc for
+`bmkp-sort-comparer'.
+
+DOC-STRING is the doc string of the new command."
+ (unless (stringp sort-order) (setq sort-order (symbol-name sort-order)))
+ (let ((command (intern (concat "bmkp-bmenu-sort-" (bmkp-replace-regexp-in-string
+ "\\s-+" "-" sort-order)))))
+ `(progn
+ (setq bmkp-sort-orders-alist (bmkp-assoc-delete-all ,sort-order (copy-sequence
+ bmkp-sort-orders-alist)))
+ (setq bmkp-sort-orders-alist (cons (cons ,sort-order ',comparer) bmkp-sort-orders-alist))
+ (defun ,command ()
+ ,(concat doc-string "\nRepeating this command cycles among normal sort, reversed \
+sort, and unsorted.")
+ (interactive)
+ (bmkp-bmenu-barf-if-not-in-menu-list)
+ (cond (;; Not this sort order - make it this sort order.
+ (not (equal bmkp-sort-comparer ',comparer))
+ (setq bmkp-sort-comparer ',comparer
+ bmkp-reverse-sort-p nil))
+ (;; Not this sort order reversed - make it reversed.
+ (not bmkp-reverse-sort-p)
+ (setq bmkp-reverse-sort-p t))
+ (t;; This sort order reversed. Change to unsorted.
+ (setq bmkp-sort-comparer nil)))
+ (message "Sorting...")
+ (bookmark-bmenu-ensure-position)
+ (let ((current-bmk (bookmark-bmenu-bookmark)))
+ (bookmark-bmenu-surreptitiously-rebuild-list)
+ (when current-bmk ; Should be non-nil, but play safe.
+ (bmkp-bmenu-goto-bookmark-named current-bmk))) ; Put cursor back on right line.
+ (when (interactive-p)
+ (bmkp-msg-about-sort-order
+ ,sort-order
+ nil
+ (cond ((and (not bmkp-reverse-sort-p)
+ (equal bmkp-sort-comparer ',comparer)) "(Repeat: reverse)")
+ ((equal bmkp-sort-comparer ',comparer) "(Repeat: unsorted)")
+ (t "(Repeat: sort)"))))))))
+
+;;;###autoload (autoload 'bmkp-define-file-sort-predicate "bookmark+")
+(defmacro bmkp-define-file-sort-predicate (att-nb)
+ "Define a predicate for sorting bookmarks by file attribute ATT-NB.
+See function `file-attributes' for the meanings of the various file
+attribute numbers.
+
+String attribute values sort alphabetically; numerical values sort
+numerically; nil sorts before t.
+
+For ATT-NB 0 (file type), a file sorts before a symlink, which sorts
+before a directory.
+
+For ATT-NB 2 or 3 (uid, gid), a numerical value sorts before a string
+value.
+
+A bookmark that has file attributes sorts before a bookmark that does
+not. A file bookmark sorts before a non-file bookmark. Only local
+files are tested for attributes - remote-file bookmarks are treated
+here like non-file bookmarks."
+ `(defun ,(intern (format "bmkp-file-attribute-%d-cp" att-nb)) (b1 b2)
+ ,(format "Sort file bookmarks by attribute %d.
+Sort bookmarks with file attributes before those without attributes
+Sort file bookmarks before non-file bookmarks.
+Treat remote file bookmarks like non-file bookmarks.
+
+B1 and B2 are full bookmarks (records) or bookmark names.
+If either is a record then it need not belong to `bookmark-alist'."
+ att-nb)
+ (setq b1 (bmkp-get-bookmark b1))
+ (setq b2 (bmkp-get-bookmark b2))
+ (let (a1 a2)
+ (cond (;; Both are file bookmarks.
+ (and (bmkp-file-bookmark-p b1) (bmkp-file-bookmark-p b2))
+ (setq a1 (file-attributes (bookmark-get-filename b1))
+ a2 (file-attributes (bookmark-get-filename b2)))
+ (cond (;; Both have attributes.
+ (and a1 a2)
+ (setq a1 (nth ,att-nb a1)
+ a2 (nth ,att-nb a2))
+ ;; Convert times and maybe inode number to floats.
+ ;; The inode conversion is kludgy, but is probably OK in practice.
+ (when (consp a1) (setq a1 (bmkp-float-time a1)))
+ (when (consp a2) (setq a2 (bmkp-float-time a2)))
+ (cond (;; (1) links, (2) maybe uid, (3) maybe gid, (4, 5, 6) times
+ ;; (7) size, (10) inode, (11) device.
+ (numberp a1)
+ (cond ((< a1 a2) '(t))
+ ((> a1 a2) '(nil))
+ (t nil)))
+ ((= 0 ,att-nb) ; (0) file (nil) < symlink (string) < dir (t)
+ (cond ((and a2 (not a1)) '(t)) ; file vs (symlink or dir)
+ ((and a1 (not a2)) '(nil))
+ ((and (eq t a2) (not (eq t a1))) '(t)) ; symlink vs dir
+ ((and (eq t a1) (not (eq t a2))) '(t))
+ ((and (stringp a1) (stringp a2))
+ (if (string< a1 a2) '(t) '(nil)))
+ (t nil)))
+ ((stringp a1) ; (2, 3) string uid/gid, (8) modes
+ (cond ((string< a1 a2) '(t))
+ ((string< a2 a1) '(nil))
+ (t nil)))
+ ((eq ,att-nb 9) ; (9) gid would change if re-created. nil < t
+ (cond ((and a2 (not a1)) '(t))
+ ((and a1 (not a2)) '(nil))
+ (t nil)))))
+ (;; First has attributes, but not second.
+ a1
+ '(t))
+ (;; Second has attributes, but not first.
+ a2
+ '(nil))
+ (;; Neither has attributes.
+ t
+ nil)))
+ (;; First is a file, second is not.
+ (bmkp-local-file-bookmark-p b1)
+ '(t))
+ (;; Second is a file, first is not.
+ (bmkp-local-file-bookmark-p b2)
+ '(nil))
+ (t;; Neither is a file.
+ nil)))))
+
+;;; This is also defined in `bookmark+-1.el'. It is used here to produce the code for
+;;; `bmkp-define-history-variables' and `bmkp-define-sort-command'.
+;;;
+(defun bmkp-types-alist ()
+ "Alist of bookmark types used by `bmkp-jump-to-type'.
+Keys are bookmark type names. Values are corresponding history variables.
+The alist is used in commands such as `bmkp-jump-to-type'."
+ (let ((entries ()))
+ (mapatoms
+ (lambda (sym)
+ (let ((name (symbol-name sym)))
+ (when (string-match "\\`bmkp-\\(.+\\)-alist-only\\'" name)
+ (push (cons (match-string 1 name)
+ (intern (format "bmkp-%s-history" (match-string 1 name))))
+ entries)))))
+ entries))
+
+;; Macro that defines Bookmark+ history variables.
+;; Use this after you define any new filter function, `bmkp-*-alist-only',
+;; for a new kind of bookmark.
+;;
+;;;###autoload (autoload 'bmkp-define-history-variables "bookmark+")
+(defmacro bmkp-define-history-variables ()
+ "Create and eval defvars for Bookmark+ history variables.
+The variables are the cdrs of `bmkp-types-alist'. They are used in
+commands such as `bmkp-jump-to-type'."
+ (dolist (entry (bmkp-types-alist))
+ `(defvar,(cdr entry) ()
+ ,(format "History for %s bookmarks." (car entry)))))
+
+;; This is compatible with Emacs 20 and later.
+;;;###autoload (autoload 'bmkp-menu-bar-make-toggle "bookmark+")
+(defmacro bmkp-menu-bar-make-toggle (command variable item-name message help
+ &optional setting-sexp &rest keywords)
+ "Define a menu-bar toggle command.
+COMMAND (a symbol) is the toggle command to define.
+VARIABLE (a symbol) is the variable to set.
+ITEM-NAME (a string) is the menu-item name.
+MESSAGE is a format string for the toggle message, with %s for the new
+ status.
+HELP (a string) is the `:help' tooltip text and the doc string first
+ line (minus final period) for the command.
+SETTING-SEXP is a Lisp sexp that sets VARIABLE, or it is nil meaning
+ set it according to its `defcustom' or using `set-default'.
+KEYWORDS is a plist for `menu-item' for keywords other than `:help'."
+ `(progn
+ (defun ,command (&optional interactively)
+ ,(concat help ".
+In an interactive call, record this option as a candidate for saving
+by \"Save Options\" in Custom buffers.")
+ (interactive "p")
+ (if ,(if setting-sexp
+ `,setting-sexp
+ `(progn
+ (custom-load-symbol ',variable)
+ (let ((set (or (get ',variable 'custom-set) 'set-default))
+ (get (or (get ',variable 'custom-get) 'default-value)))
+ (funcall set ',variable (not (funcall get ',variable))))))
+ (message ,message "enabled globally")
+ (message ,message "disabled globally"))
+ ;; `customize-mark-as-set' must only be called when a variable is set interactively,
+ ;; because the purpose is to mark the variable as a candidate for `Save Options', and we
+ ;; do not want to save options that the user has already set explicitly in the init file.
+ (when (and interactively (fboundp 'customize-mark-as-set))
+ (customize-mark-as-set ',variable)))
+ '(menu-item ,item-name ,command
+ :help ,help
+ :button (:toggle . (and (default-boundp ',variable) (default-value ',variable)))
+ ,@keywords)))
+
+;;; Not used currently. Provided so you can use it in your own code, if appropriate.
+;;;###autoload (autoload 'bmkp-with-bookmark-dir "bookmark+")
+(defmacro bmkp-with-bookmark-dir (bookmark &rest body)
+ "Evaluate BODY forms with BOOKMARK location as `default-directory'.
+If BOOKMARK has no location then use nil as `default-directory'."
+ `(let* ((loc (bookmark-location ,bookmark))
+ (default-directory (and (stringp loc) (not (member loc (list bmkp-non-file-filename
+ "-- Unknown location --")))
+ (if (file-directory-p loc) loc (file-name-directory loc)))))
+ ,@body))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(provide 'bookmark+-mac)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; bookmark+-mac.el ends here
--- /dev/null
+;;; bookmark+.el --- Bookmark+: extensions to standard library `bookmark.el'.
+;;
+;; Filename: bookmark+.el
+;; Description: Bookmark+: extensions to standard library `bookmark.el'.
+;; Author: Drew Adams, Thierry Volpiatto
+;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com")
+;; Copyright (C) 2000-2022, Drew Adams, all rights reserved.
+;; Copyright (C) 2009, Thierry Volpiatto, all rights reserved.
+;; Created: Fri Sep 15 07:58:41 2000
+;; Version: 2021.09.19
+;; Last-Updated: Fri Jan 14 12:52:46 2022 (-0800)
+;; By: dradams
+;; Update #: 15072
+;; URL: https://www.emacswiki.org/emacs/download/bookmark%2b.el
+;; Doc URL: https://www.emacswiki.org/emacs/BookmarkPlus
+;; Keywords: bookmarks, bookmark+, projects, placeholders, annotations, search, info, url, eww, w3m, gnus
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x, 26.x
+;;
+;; Features that might be required by this library:
+;;
+;; `apropos', `apropos+', `avoid', `backquote', `bookmark',
+;; `bookmark+', `bookmark+-1', `bookmark+-bmu', `bookmark+-key',
+;; `bookmark+-lit', `button', `bytecomp', `cconv', `cl', `cl-lib',
+;; `cmds-menu', `col-highlight', `crosshairs', `fit-frame',
+;; `font-lock', `font-lock+', `frame-fns', `gv', `help+',
+;; `help-fns', `help-fns+', `help-macro', `help-macro+',
+;; `help-mode', `hl-line', `hl-line+', `info', `info+', `kmacro',
+;; `macroexp', `menu-bar', `menu-bar+', `misc-cmds', `misc-fns',
+;; `naked', `pp', `pp+', `radix-tree', `rect', `replace',
+;; `second-sel', `strings', `syntax', `text-mode', `thingatpt',
+;; `thingatpt+', `vline', `w32browser-dlgopen', `wid-edit',
+;; `wid-edit+'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Bookmark+: extensions to standard library `bookmark.el'.
+;;
+;; The Bookmark+ libraries are these:
+;;
+;; `bookmark+.el' - main (driver) library (this file)
+;; `bookmark+-mac.el' - Lisp macros
+;; `bookmark+-lit.el' - (optional) code for highlighting bookmarks
+;; `bookmark+-bmu.el' - code for the `*Bookmark List*' (bmenu)
+;; `bookmark+-1.el' - other required code (non-bmenu)
+;; `bookmark+-key.el' - key and menu bindings
+;;
+;; `bookmark+-doc.el' - documentation (comment-only file)
+;; `bookmark+-chg.el' - change log (comment-only file)
+;;
+;; The documentation (in `bookmark+-doc.el') includes how to
+;; byte-compile and install Bookmark+. The documentation is also
+;; available in these ways:
+;;
+;; 1. From the bookmark list (`C-x r l'):
+;; Use `?' to show the current bookmark-list status and general
+;; help, then click link `Doc in Commentary' or link `Doc on the
+;; Web'.
+;;
+;; 2. From the Emacs-Wiki Web site:
+;; https://www.emacswiki.org/emacs/BookmarkPlus.
+;;
+;; 3. From the Bookmark+ group customization buffer:
+;; `M-x customize-group bookmark-plus', then click link
+;; `Commentary'.
+;;
+;; (The commentary links in #1 and #3 work only if you have library
+;; `bookmark+-doc.el' in your `load-path'.)
+;;
+;; To report Bookmark+ bugs: `M-x customize-group bookmark-plus'
+;; and then follow (e.g. click) the link `Send Bug Report', which
+;; helps you prepare an email to me.
+;;
+;;
+;; ****** NOTE ******
+;;
+;; Whenever you update Bookmark+ (i.e., download new versions of
+;; Bookmark+ source files), I recommend that you do the
+;; following:
+;;
+;; 1. Delete all existing byte-compiled Bookmark+ files
+;; (bookmark+*.elc).
+;; 2. Load Bookmark+ (`load-library' or `require').
+;; 3. Byte-compile the source files.
+;;
+;; In particular, always load `bookmark+-mac.el' (not
+;; `bookmark+-mac.elc') before you byte-compile new versions of
+;; the files, in case there have been any changes to Lisp macros
+;; (in `bookmark+-mac.el').
+;;
+;; ******************
+;;
+;;
+;; ****** NOTE ******
+;;
+;; On 2010-06-18, I changed the prefix used by package Bookmark+
+;; from `bookmarkp-' to `bmkp-'. THIS IS AN INCOMPATIBLE CHANGE.
+;; I apologize for the inconvenience, but the new prefix is
+;; preferable for a number of reasons, including easier
+;; distinction from standard `bookmark.el' names.
+;;
+;; This change means that YOU MUST MANUALLY REPLACE ALL
+;; OCCURRENCES of `bookmarkp-' by `bmkp-' in the following
+;; places, if you used Bookmark+ prior to this change:
+;;
+;; 1. In your init file (`~/.emacs') or your `custom-file', if
+;; you have one. This is needed if you customized any
+;; Bookmark+ features.
+;;
+;; 2. In your default bookmark file, `bookmark-default-file'
+;; (`~/.emacs.bmk'), and in any other bookmark files you might
+;; have.
+;;
+;; 3. In your `*Bookmark List*' state file,
+;; `bmkp-bmenu-state-file' (`~/.emacs-bmk-bmenu-state.el').
+;;
+;; 4. In your `*Bookmark List*' commands file,
+;; `bmkp-bmenu-commands-file' (`~/.emacs-bmk-bmenu-commands.el'),
+;; if you have one.
+;;
+;; You can do this editing in a virgin Emacs session (`emacs
+;; -Q'), that is, without loading Bookmark+.
+;;
+;; Alternatively, you can do this editing in an Emacs session
+;; where Bookmark+ has been loaded, but in that case you must
+;; TURN OFF AUTOMATIC SAVING of both your default bookmark file
+;; and your `*Bookmark List*' state file. Otherwise, when you
+;; quit Emacs your manually edits will be overwritten.
+;;
+;; To turn off this automatic saving, you can use `M-~' and `M-l'
+;; in buffer `*Bookmark List*' (commands
+;; `bmkp-toggle-saving-bookmark-file' and
+;; `bmkp-toggle-saving-menu-list-state' - they are also in the
+;; `Bookmark+' menu).
+;;
+;;
+;; Again, sorry for this inconvenience.
+;;
+;; ******************
+;;
+;;
+;; Commands defined here:
+;;
+;; `bmkp-version'.
+;;
+;; Internal variables defined here:
+;;
+;; `bmkp-version-number'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(require 'bookmark) ; Vanilla Emacs.
+
+;;;###autoload (autoload 'bmkp-version-number "bookmark+")
+(defconst bmkp-version-number "2018.10.17")
+
+;;;###autoload (autoload 'bmkp-version "bookmark+")
+(defun bmkp-version ()
+ "Show version number of library `bookmark+.el'."
+ (interactive)
+ (message "Bookmark+, version %s" bmkp-version-number))
+
+;; This was made automatically buffer-local for vanilla Emacs 28. Do it here, for all Bookmark+ files.
+(defvar bookmark-annotation-name nil
+ "Name of bookmark under edit in `bookmark-edit-annotation-mode'.")
+(make-variable-buffer-local 'bookmark-annotation-name)
+
+;;;###autoload (autoload 'bookmark-bmenu-buffer "bookmark+")
+;; This was added for vanilla Emacs 28. Add it here for older releases.
+(defconst bookmark-bmenu-buffer "*Bookmark List*"
+ "Name of buffer used by vanilla Emacs for the bookmark-list display.")
+
+;;;###autoload (autoload 'bookmark-plus "bookmark+")
+(defgroup bookmark-plus nil
+ "Bookmark enhancements."
+ :prefix "bmkp-" :group 'bookmark
+ :link `(url-link :tag "Send Bug Report"
+ ,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
+Bookmark+ bug: \
+&body=Describe bug here, starting with `emacs -Q'. \
+Don't forget to mention your Emacs and library versions."))
+ :link '(url-link :tag "Download" "https://www.emacswiki.org/emacs/download/bookmark%2b.el")
+ :link '(url-link :tag "Description" "https://www.emacswiki.org/emacs/BookmarkPlus")
+ :link '(emacs-commentary-link :tag "Commentary" "bookmark+"))
+
+;; NOTE:
+;; $$$$$$ Currently all vanilla Emacs functions that use constant `bookmark-bmenu-buffer' are
+;; already redefined for Bookmark+. But if vanilla Emacs adds more such functions, and if those
+;; functions could be invoked somehow when using Bookmark+, and if `bmkp-bmenu-buffer' has a
+;; different value from `bookmark-bmenu-buffer', then some adjustment of Bookmark+ code will be
+;; needed, to make sure the `bmkp-bmenu-buffer' value gets used instead.
+;;
+;;;###autoload (autoload 'bmkp-bmenu-buffer "bookmark+")
+(defcustom bmkp-bmenu-buffer bookmark-bmenu-buffer
+ "Name of buffer used by Bookmark+ for the bookmark-list display.
+The default value is that of vanilla Emacs constant `bookmark-bmenu-buffer'."
+ :type 'string :group 'bookmark-plus)
+
+
+
+;; Load Bookmark+ libraries.
+;;
+(eval-when-compile
+ (or (condition-case nil
+ (load-library "bookmark+-mac") ; Lisp macros.
+ (error nil)) ; Use load-library to ensure latest .elc.
+ (require 'bookmark+-mac))) ; Require, so can load separately if not on `load-path'.
+
+(require 'bookmark+-lit nil t) ; Optional (soft require) - no error if not found. If you do
+ ; not want to use `bookmark+-lit.el' then simply do not put
+ ; that file in your `load-path'.
+(require 'bookmark+-bmu) ; `*Bookmark List*' (aka "menu list") stuff.
+(require 'bookmark+-1) ; Rest of Bookmark+, except keys & menus.
+(require 'bookmark+-key) ; Keys & menus.
+
+;;;;;;;;;;;;;;;;;;;;;;;
+
+(provide 'bookmark+)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; bookmark+.el ends here