Find file
Fetching contributors…
Cannot retrieve contributors at this time
11985 lines (10730 sloc) 614 KB
;;; 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-2016, Drew Adams, all rights reserved.
;; Copyright (C) 2009, Thierry Volpiatto, all rights reserved.
;; Created: Mon Jul 12 13:43:55 2010 (-0700)
;; Last-Updated: Thu Dec 31 12:19:02 2015 (-0800)
;; By: dradams
;; Update #: 7849
;; URL: http://www.emacswiki.org/bookmark+-1.el
;; Doc URL: http://www.emacswiki.org/BookmarkPlus
;; Keywords: bookmarks, bookmark+, placeholders, annotations, search, info, url, w3m, gnus
;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x
;;
;; Features that might be required by this library:
;;
;; `bookmark', `bookmark+-1', `ffap', `pp', `thingatpt',
;; `thingatpt+'.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; 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:
;; http://www.emacswiki.org/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:
;; http://dto.freeshell.org/notebook/Linkd.html.
;;
;; (@> "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-bookmark', `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-auto-idle-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-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-compilation-target-set',
;; `bmkp-compilation-target-set-all', `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-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-send',
;; `bmkp-edit-bookmark-records-send', `bmkp-edit-tags',
;; `bmkp-edit-tags-send', `bmkp-edit-this-annotation',
;; `bmkp-empty-file', `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-auto-idle-bookmark-mode' (Emacs 21+),
;; `bmkp-gnus-jump', `bmkp-gnus-jump-other-window',
;; `bmkp-image-jump', `bmkp-image-jump-other-window',
;; `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-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-repeat', `bmkp-next-bookmark',
;; `bmkp-next-bookmark-list-bookmark',
;; `bmkp-next-bookmark-list-bookmark-repeat',
;; `bmkp-next-bookmark-repeat', `bmkp-next-bookmark-this-buffer',
;; `bmkp-next-bookmark-this-buffer-repeat',
;; `bmkp-next-bookmark-this-file',
;; `bmkp-next-bookmark-this-file/buffer',
;; `bmkp-next-bookmark-this-file/buffer-repeat',
;; `bmkp-next-bookmark-this-file-repeat', `bmkp-next-bookmark-w32',
;; `bmkp-next-bookmark-w32-repeat', `bmkp-next-desktop-bookmark',
;; `bmkp-next-desktop-bookmark-repeat', `bmkp-next-dired-bookmark',
;; `bmkp-next-dired-bookmark-repeat', `bmkp-next-file-bookmark',
;; `bmkp-next-file-bookmark-repeat', `bmkp-next-gnus-bookmark',
;; `bmkp-next-gnus-bookmark-repeat', `bmkp-next-info-bookmark',
;; `bmkp-next-info-bookmark-repeat', `bmkp-next-lighted-bookmark',
;; `bmkp-next-lighted-bookmark-repeat',
;; `bmkp-next-local-file-bookmark',
;; `bmkp-next-local-file-bookmark-repeat',
;; `bmkp-next-man-bookmark', `bmkp-next-man-bookmark-repeat',
;; `bmkp-next-non-file-bookmark',
;; `bmkp-next-non-file-bookmark-repeat',
;; `bmkp-next-remote-file-bookmark',
;; `bmkp-next-remote-file-bookmark-repeat',
;; `bmkp-next-specific-buffers-bookmark',
;; `bmkp-next-specific-buffers-bookmark-repeat',
;; `bmkp-next-specific-files-bookmark',
;; `bmkp-next-specific-files-bookmark-repeat',
;; `bmkp-next-variable-list-bookmark',
;; `bmkp-next-variable-list-bookmark-repeat',
;; `bmkp-next-url-bookmark', `bmkp-next-url-bookmark-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-bookmark',
;; `bmkp-previous-bookmark-repeat',
;; `bmkp-previous-bookmark-this-buffer',
;; `bmkp-previous-bookmark-this-buffer-repeat',
;; `bmkp-previous-bookmark-this-file',
;; `bmkp-previous-bookmark-this-file/buffer',
;; `bmkp-previous-bookmark-this-file/buffer-repeat',
;; `bmkp-previous-bookmark-this-file-repeat',
;; `bmkp-previous-bookmark-w32',
;; `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-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-icicle-search-hits-bookmark',
;; `bmkp-set-izones-bookmark', `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-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-saving-bookmark-file',
;; `bmkp-toggle-saving-menu-list-state',
;; `bmkp-toggle-temporary-bookmark',
;; `bmkp-turn-on-auto-idle-bookmark-mode' (Emacs 21+),
;; `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-auto-idle-bookmark-min-distance',
;; `bmkp-auto-idle-bookmark-mode-delay',
;; `bmkp-auto-idle-bookmark-mode-lighter',
;; `bmkp-auto-idle-bookmark-mode-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-jump-save-before-flag.',
;; `bmkp-desktop-no-save-vars',
;; `bmkp-guess-default-handler-for-file-flag',
;; `bmkp-handle-region-function', `bmkp-incremental-filter-delay',
;; `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-multi-tabs-flag',
;; `bmkp-write-bookmark-file-hook'.
;;
;; Non-interactive functions defined here:
;;
;; `bmkext-jump-gnus', `bmkext-jump-man', `bmkext-jump-w3m',
;; `bmkext-jump-woman', `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-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-bookmark-type',
;; `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-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-full-tag', `bmkp-function-alist-only',
;; `bmkp-function-bookmark-p', `bmkp-get-autofile-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-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-function',
;; `bmkp-jump-gnus', `bmkp-jump-icicle-search-hits',
;; `bmkp-jump-man', `bmkp-jump-sequence', `bmkp-jump-snippet',
;; `bmkp-jump-url-browse', `bmkp-jump-variable-list',
;; `bmkp-jump-w3m', `bmkp-jump-w3m-new-session',
;; `bmkp-jump-w3m-only-one-tab', `bmkp-jump-woman',
;; `bmkp-last-specific-buffer-alist-only',
;; `bmkp-last-specific-buffer-p',
;; `bmkp-last-specific-file-alist-only',
;; `bmkp-last-specific-file-p', `bmkp-line-number-at-pos',
;; `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-gnus-record',
;; `bmkp-make-icicle-search-hits-record', `bmkp-make-man-record',
;; `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-not-near-other-auto-idle-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-readable-p',
;; `bmkp-read-bookmark-file-default',
;; `bmkp-read-bookmark-file-name', `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-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'.
;;
;; Internal variables defined here:
;;
;; `bmkp-after-set-hook', `bmkp-autofile-history',
;; `bmkp-auto-idle-bookmark-mode-timer',
;; `bmkp-auto-idle-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-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-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-types-alist', `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-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-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 functions defined in `info.el'
;; have been REDEFINED HERE:
;;
;; `Info-bookmark-jump' (Emacs 20-22), `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-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)
(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-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-light-priorities) ; In `bookmark+-lit.el'
(defvar bmkp-temporary-bookmarking-mode) ; Here
(defvar bmkp-global-auto-idle-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-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 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 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-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)
;;;###autoload (autoload 'bmkp-auto-idle-bookmark-min-distance "bookmark+")
(defcustom bmkp-auto-idle-bookmark-min-distance 1000
"*Minimum number of chars between automatic bookmark positions."
:type '(choice
(const :tag "No minumum distance" nil)
(integer :tag "At least this many chars" :value 1000))
:group 'bookmark-plus)
;; Emacs 20 only.
;;;###autoload (autoload 'bmkp-auto-idle-bookmark-mode "bookmark+")
(unless (fboundp 'define-minor-mode)
(defcustom bmkp-auto-idle-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-auto-idle-bookmark-mode'."
:set (lambda (symbol value) (bmkp-auto-idle-bookmark-mode (if value 1 -1)))
:initialize 'custom-initialize-default
:type 'boolean :group 'bookmark-plus :require 'bookmark+))
;;;###autoload (autoload 'bmkp-auto-idle-bookmark-mode-delay "bookmark+")
(defcustom bmkp-auto-idle-bookmark-mode-delay 60
"*Number of seconds delay before automatically setting a bookmark.
Such automatic bookmarking is controlled by
`bmkp-temporary-bookmarking-mode'."
:type 'integer :group 'bookmark-plus)
;;;###autoload (autoload 'bmkp-auto-idle-bookmark-mode-lighter "bookmark+")
(defcustom bmkp-auto-idle-bookmark-mode-lighter " Auto-Bmk"
"*Lighter for `bmkp-auto-idle-bookmark-mode'.
This string shows in the mode line when `bmkp-auto-idle-bookmark-mode'
is enabled. Set this to nil or \"\" if you do not want any lighter."
:type 'string :group 'bookmark-plus)
;;;###autoload (autoload 'bmkp-auto-idle-bookmark-mode-set-function "bookmark+")
(defcustom bmkp-auto-idle-bookmark-mode-set-function #'bmkp-set-autonamed-bookmark-at-line
"*Function used to set an automatic bookmark.
Used by `bmkp-temporary-bookmarking-mode'.
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\\} %s" "^[0-9]+ %s")
"*Format string to match an autonamed bookmark name.
It must have a single `%s' to accept the buffer name."
: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-autofile-bookmark-p', `bmkp-annotated-bookmark-p',
`bmkp-autonamed-bookmark-for-buffer-p', `bmkp-autonamed-bookmark-p',
`bmkp-autonamed-this-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-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-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 moficication. 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)
(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-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)
;;;###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-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)
;; 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-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)
;;;###autoload (autoload 'bmkp-w3m-allow-multi-tabs-flag "bookmark+")
(defcustom bmkp-w3m-allow-multi-tabs-flag t
"*Non-nil means jump to W3M bookmarks in a new session."
: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)
;;(@* "Internal Variables")
;;; Internal Variables -----------------------------------------------
(defconst bmkp-non-file-filename " - no file -"
"Name to use for `filename' entry, for non-file bookmarks.")
(defconst bmkp-types-alist '(("autofile" . bmkp-autofile-history)
("autonamed" . bmkp-autonamed-history)
("bookmark-file" . bmkp-bookmark-file-history)
("bookmark-list" . bmkp-bookmark-list-history)
("desktop" . bmkp-desktop-history)
("dired" . bmkp-dired-history)
("dired-this-dir" . bmkp-dired-history)
("file" . bmkp-file-history)
("file-this-dir" . bmkp-file-history)
("gnus" . bmkp-gnus-history)
("image" . bmkp-image-history)
("info" . bmkp-info-history)
("local-file" . bmkp-local-file-history)
("man" . bmkp-man-history)
("non-file" . bmkp-non-file-history)
("region" . bmkp-region-history)
("remote-file" . bmkp-remote-file-history)
("snippet" . bmkp-snippet-history)
("specific-buffers" . bmkp-specific-buffers-history)
("specific-files" . bmkp-specific-files-history)
("temporary" . bmkp-temporary-history)
("url" . bmkp-url-history)
("variable-list" . bmkp-variable-list-history))
"Alist of bookmark types used by `bmkp-jump-to-type'.
Keys are bookmark type names. Values are corresponding history variables.")
(defvar bmkp-autofile-history () "History for autofile bookmarks.")
(defvar bmkp-autonamed-history () "History for autonamed bookmarks.")
(defvar bmkp-bookmark-file-history () "History for bookmark-file bookmarks.")
(defvar bmkp-bookmark-list-history () "History for bookmark-list bookmarks.")
(defvar bmkp-desktop-history () "History for desktop bookmarks.")
(defvar bmkp-dired-history () "History for Dired bookmarks.")
(defvar bmkp-file-history () "History for file bookmarks.")
(defvar bmkp-gnus-history () "History for Gnus bookmarks.")
(defvar bmkp-image-history () "History for image-file bookmarks.")
(defvar bmkp-info-history () "History for Info bookmarks.")
(defvar bmkp-last-bmenu-state-file nil "Last value of option `bmkp-bmenu-state-file'.")
(defvar bmkp-local-file-history () "History for local-file bookmarks.")
(defvar bmkp-man-history () "History for `man'-page bookmarks.")
(defvar bmkp-non-file-history () "History for buffer (non-file) bookmarks.")
(defvar bmkp-region-history () "History for bookmarks that activate the region.")
(defvar bmkp-remote-file-history () "History for remote-file bookmarks.")
(defvar bmkp-snippet-history () "History for snippet bookmarks.")
(defvar bmkp-specific-buffers-history () "History for specific-buffers bookmarks.")
(defvar bmkp-specific-files-history () "History for specific-files bookmarks.")
(defvar bmkp-temporary-history () "History for temporary bookmarks.")
(defvar bmkp-url-history () "History for URL bookmarks.")
(defvar bmkp-variable-list-history () "History for variable-list bookmarks.")
(defvar bmkp-w3m-history () "History for W3M bookmarks.")
(defvar bmkp-after-set-hook nil "Hook run after `bookmark-set' sets a bookmark.")
(defvar bmkp-auto-idle-bookmarks ()
"Alist of bookmarks that were created automatically during this session.")
(defvar bmkp-auto-idle-bookmark-mode-timer nil
"Timer for `bmkp-auto-idle-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-auto-idle-bookmark-mode-timer)")
(unless (< emacs-major-version 21) (make-variable-buffer-local 'bmkp-auto-idle-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-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-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
"Association list of bookmarks and their 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 information. The order of the
entries in PARAM-ALIST is not important. The possible entries are
described below. An entry with a key but null value means the entry
is not used.
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))))
;; Requires `info.el' explicitly (not autoloaded for `Info-find-node'.
(defun Info-bookmark-jump (bookmark)
"Jump to Info bookmark BOOKMARK.
BOOKMARK is a bookmark name or a bookmark record."
(require 'info)
;; Implements the `handler' for the record type returned by `Info-bookmark-make-record'.
(let* ((file (bookmark-prop-get bookmark 'filename))
(info-node (bookmark-prop-get bookmark 'info-node))
(buf (save-window-excursion ; VANILLA EMACS FIXME: doesn't work with frames!
(Info-find-node file info-node) (current-buffer))))
;; Use `bookmark-default-handler' to move to appropriate location within Info node.
(bookmark-default-handler
`("" (buffer . ,buf) . ,(bmkp-bookmark-data-from-record bookmark)))))
(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 property PROP of BOOKMARK, or nil if no such property.
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 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)
;; REPLACES ORIGINAL in `bookmark.el'.
;;
;; Doc string does not mention `bookmark-alist': does NOT test whether BOOKMARK is 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 bookmark name then it is looked up in `bookmark-alist'.
If it is a record then it is NOT looked up (need not belong)."
(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'.
;;
;; 1. If BOOKMARK is a bookmark-name string that has non-nil property `bmkp-full-record'
;; then look up the bookmark that is the value of that property in `bookmark-alist', and
;; if found return it.
;; 2. Handle the should-not-happen case of non-string, non-cons.
;; 3. Document NOERROR in doc string.
;;
(defun bookmark-get-bookmark (bookmark &optional noerror)
"Return the full bookmark (record) that corresponds to BOOKMARK.
BOOKMARK is a bookmark name or a bookmark record.
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.
If BOOKMARK is a bookmark name instead of a full bookmark then return
what `bmkp-bookmark-record-from-name' (with no MEMP check) returns.
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 `bookmark-get-bookmark'
only when you do NOT want to look up the bookmark in
`bookmark-alist'."
;; The first test means that any cons with a string car is considered a bookmark.
;; We test for the string (the name) so that you can distinguish, for example, a list of bookmarks
;; from a single bookmark - just consp is not enough for that.
(cond ((and (consp bookmark) (stringp (car bookmark))) bookmark) ; No test of alist membership.
((stringp bookmark) (bmkp-bookmark-record-from-name bookmark noerror)) ; No MEMP check.
(t (and (not 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-UPDATE-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-auto-idle-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-update-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-UPDATE-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-auto-idle-bmk-p)
(not (memq bmk bmkp-auto-idle-bookmarks)))
(setq bmkp-auto-idle-bookmarks (cons bmk bmkp-auto-idle-bookmarks)))
(setq bookmark-current-bookmark bname)
(unless no-update-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 (bmkp-looking-at-p "^#") (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.
;;
;;;###autoload (autoload 'bookmark-edit-annotation "bookmark+")
(defun bookmark-edit-annotation (bookmark)
"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 (and (not current-prefix-arg) (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))))
(pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*"))
(bookmark-insert-annotation bookmark)
(bookmark-edit-annotation-mode)
(set (make-local-variable '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)
"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 alist argument used for completion is ALIST or, if nil,
`bookmark-alist'.
Optional arg PRED is a predicate used for completion.
Optional arg HIST is a history variable for completion. Default is
`bookmark-history'.
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))
;; 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
(dolist (bmk bmks)
(put-text-property 0 (length (car bmk)) 'bmkp-full-record bmk (car bmk))))
bmks))
;; REPLACES ORIGINAL in `bookmark.el'.
;;
;; 1. Use `bookmark-make-record'.
;; 2. Use special default prompts for active region, 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-UPDATE-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-update-p) ; `C-x r M', `C-x p 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 optional arg NO-UPDATE-P 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 ((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))))
;; 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)))
(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)))))
(bookmark-store bname (cdr record) (consp parg) no-update-p (not interactivep))
(when (and interactivep bmkp-prompt-for-tags-flag)
(bmkp-add-tags bname (bmkp-read-tags-completing) 'NO-UPDATE-P)) ; Do not refresh tags 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)))
;; Maybe make bookmark temporary.
(if bmkp-autotemp-all-when-set-p
(bmkp-make-bookmark-temporary bname)
(catch 'bookmark-set
(dolist (pred bmkp-autotemp-bookmark-predicates)
(when (and (functionp pred) (funcall pred bname))
(bmkp-make-bookmark-temporary bname)
(throw 'bookmark-set t)))))
(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'.
;;
;; Put full bookmark record on the name as property `bmkp-full-record'.
;; Add BOOKMARK to `bmkp-modified-bookmarks'.
;;
(defun bookmark-set-name (bookmark newname)
"Set name of BOOKMARK to NEWNAME.
BOOKMARK is a bookmark name or a bookmark record."
(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."
(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. Add to beginning, not end, of bookmark record.
;; 2. Do not use `nconc'.
;; 3. Respect both old and newer bookmark formats.
;; 4. Add BOOKMARK to `bmkp-modified-bookmarks'.
;;
(defun bookmark-prop-set (bookmark prop val)
"Set the property PROP of BOOKMARK to VAL.
BOOKMARK is a bookmark name or a bookmark record.
If it is a record then it need not belong to `bookmark-alist'."
(let* ((bmk (bookmark-get-bookmark bookmark))
(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 p 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, `switch-to-buffer' is used.
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 'switch-to-buffer) 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 p j', `C-x p o', `C-x p 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'.
;;
;; 1. Invoke MS Windows `Open' action if `bmkp-use-w32-browser-p' and if `w32-browser' is defined.
;;
;; 2. Favor property `file-handler' over `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' property that 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) (bookmark-get-bookmark bookmark)))
(t
(condition-case err
(funcall 'bookmark-default-handler (bookmark-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)
(bookmark-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. Support regions, buffer names, and property `file-handler'.
;; 2. 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 properties `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 (bookmark-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-UPDATE-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-update-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-UPDATE-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 "*Bookmark List*")
(get-buffer-window (get-buffer "*Bookmark List*") 0)
(not no-update-p))
(with-current-buffer (get-buffer "*Bookmark List*") ; 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 p I' (original: `C-x p 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. Pass full bookmark to the various "get" functions.
;; 2. 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 record then it need not belong to `bookmark-alist'.
Look first for property `location', then for property `filename', then
for property `buffer-name'. Return the first such property 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)
(bookmark-prop-get bookmark '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. Rename also in marked and omitted lists.
;; 3. Use `bmkp-bookmark-record-from-name', not `bookmark-get-bookmark'.
;; 4. Use `bmkp-completing-read-lax', not `read-from-minibuffer'.
;; 5. Put `bmkp-full-record' property on new name.
;; 3. Use `bmkp-bookmark-record-from-name', not `bookmark-get-bookmark'.
;; 4. 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)
;; Put the bookmark on the 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 (bmkp-bookmark-record-from-name newname)
newname)
(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 "*Bookmark List*") (get-buffer-window (get-buffer "*Bookmark List*") 0))
(with-current-buffer (get-buffer "*Bookmark List*")
(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 p 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-in-alist', not `bookmark-get-bookmark'.
;; 4. Remove highlighting for the bookmark.
;; 5. Doc string includes note about `S-delete' for Icicles.
;; 6. Update `bmkp-latest-bookmark-alist', `bmkp-bmenu-omitted-bookmarks', and `bmkp-auto-idle-bookmarks'.
;; 7. 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 p 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 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 (bookmark-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-auto-idle-bookmarks (delq bmk bmkp-auto-idle-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 p 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, use file `bmkp-current-bookmark-file'.
With non-nil PARG and non-nil FILE, use file FILE.
With non-nil PARG and nil FILE, prompt the user for the file to use."
(interactive "P")
(bookmark-maybe-load-default-file)
(let ((file-to-save
(cond ((and (not parg) (not file)) bmkp-current-bookmark-file)
((and (not parg) file) file)
((and parg (not file)) (bmkp-read-bookmark-file-name
"File to save bookmarks in: " nil
(bmkp-read-bookmark-file-default))))))
(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?
;; 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.
;; 4. Insert code piecewise, to improve performance when saving `bookmark-alist'.
;; (Do not let `pp' parse all of `bookmark-alist' at once.)
;; 5. 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.
;; 6. Bind `print-circle' around `pp', to record bNAME with `bmkp-full-record' prop, when appropriate.
;; 7. Use `case', not `cond'.
;; 8. 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' property 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'..."))
(print-length nil)
(print-level nil)
(rem-all-p (or (not (> emacs-major-version 20)) ; Cannot do `(not (boundp 'print-circle))'.
(not bmkp-propertize-bookmark-names-flag)))
(existing-buf (get-file-buffer file))
bname fname last-fname start end)
(message msg 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.
(bookmark-insert-file-format-version-stamp)
(insert "(\n)"))
(setq start (or (save-excursion (goto-char (point-min))
(search-forward (concat bookmark-end-of-version-stamp-marker "(")
nil t))
(error "Invalid bookmark-file"))
end (or (save-excursion (goto-char start) (and (looking-at ")") start)) ; Empty bmk list: ().
(save-excursion (goto-char (point-max)) (re-search-backward "^)" nil t))
(error "Invalid bookmark-file")))
(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 (car 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))
(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 ((sname (copy-sequence (car bmk))))
(set-text-properties 0 (length sname) () sname)
sname)
"\"\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")))))
(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)))))
(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. Use `bmkp-read-bookmark-file-name', not `read-file-name', and use different default.
;; 3. 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.
;; 4. If the bookmark-file buffer already existed, do not kill it after loading.
;; 5. Set `bookmarks-already-loaded' regardless of FILE (not just `bookmark-default-file').
;; 6. Update `bmkp-sorted-alist' (it's a cache).
;; 7. Final msg says whether overwritten.
;; 8. Run `bmkp-read-bookmark-file-hook' after reading the bookmark file.
;; 9. 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 p l'
"Load bookmarks from FILE (which must be in the standard format).
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)))
(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)))
(with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file))
(goto-char (point-min))
(bookmark-maybe-upgrade-file-format)
(let ((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))
(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)))
;; REPLACES ORIGINAL in `bookmark.el'.
;;
;; 1. Make it a command (added `interactive' spec).
;; 2. Handle external annotations (jump to their destinations).
;; 3. Added optional arg MSG-P. Show message if no annotation.
;; 4. If `bookmark-automatically-show-annotations' is `edit' then this is `bookmark-edit-annotation'.
;; 5. Name buffer after the bookmark.
;; 6. Highlight the title, using face `bmkp-heading'.
;; 7. MSG-P means message if no annotation.
;; 8. Set `bookmark-annotation-name'.
;; 9. Manage `buffer-modified-p'.
;; 10. Use `, not ', in title. (Both are tolerated.)
;; 11. Fit frame to buffer if `one-windowp'.
;; 12. Restore frame selection.
;;
;;;###autoload (autoload 'bookmark-show-annotation "bookmark+")
(defun bookmark-show-annotation (bookmark &optional msg-p)
"Show the annotation for BOOKMARK, or follow it if external.
BOOKMARK is a bookmark name or a bookmark record.
If it is a record then it need not belong to `bookmark-alist'.
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))))
(let* ((bmk (bookmark-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))
(set (make-local-variable '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 name `*Bookmark Annotations*', not `*Bookmark Annotation*'.
;; 3. Don't list bookmarks that have no annotation.
;; 4. Highlight bookmark names. Don't indent annotations. Add a blank line after each annotation.
;; 5. Use `view-mode'. `q' uses `quit-window'.
;; 6. Fit frame to buffer if `one-windowp'.
;; 7. Restore frame selection.
;;
;;;###autoload (autoload 'bookmark-show-all-annotations "bookmark+")
(defun bookmark-show-all-annotations ()
"Display the annotations for all bookmarks.
If called from buffer `*Bookmark List*' then the annotations are shown
in the current sort order."
(interactive)
(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) "*Bookmark List*")
(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))
(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-*') -----------------------------------
(if (fboundp 'find-tag-default-as-regexp)
(defalias 'bmkp-read-regexp 'read-regexp) ; Emacs 24.3+
;; 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 (prompt &optional 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.
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'."
(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 (prompt &optional default history) ; Emacs 20-21
"Read and return a string.
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'."
(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))))
(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 bookmark-alist) bookmark))
((stringp bookmark) (bmkp-bookmark-record-from-name bookmark noerror 'MEMP))
(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)
"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. If nil, use `bookmark-alist'.
NAMES-ONLY-P non-nil means return bookmark names, not full bookmarks.
If NAMES-ONLY-P is `lax' then completion is lax."
(let ((bmks ())
(bmk t))
(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)
"Read a bookmark name, prompting with PROMPT.
Like `bookmark-completing-read', but completion is lax: 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 t))
(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 default alist pred hist laxp)
"Helper for `bookmark-completing-read' and `bmkp-completing-read-lax'.
LAXP non-nil means use lax (non-strict) completion."
(bookmark-maybe-load-default-file)
(setq alist (or 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.
(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.
DISPLAY-FUNCTION is passed to `bookmark--jump-via'.
Non-nil optional arg FLIP-USE-REGION-P means temporarily flip the
value of `bmkp-use-region'."
(setq bookmark (bookmark-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)
"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)
(set (make-local-variable 'bookmark-annotation-name) bookmark))
;;;###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 (bookmark-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))
(switch-to-buffer (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))
(set (make-local-variable '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 (bookmark-get-bookmark bookmark-annotation-name 'NOERROR))
(bname (bookmark-name-from-full-record bmk))
(obuf (current-buffer)))
(unless bname (error "No such bookmark: `%s'" bmk))
(switch-to-buffer (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))
(set (make-local-variable 'bookmark-annotation-name) bmk)
(kill-buffer obuf)))
;;;###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 p 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