New org capture template
[emacs.git] / .emacs.d / elisp / icicle / bookmark+-1.el
1 ;;; bookmark+-1.el - First part of package Bookmark+.
2 ;;
3 ;; Filename: bookmark+-1.el
4 ;; Description: First part of package Bookmark+.
5 ;; Author: Drew Adams, Thierry Volpiatto
6 ;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com")
7 ;; Copyright (C) 2000-2012, Drew Adams, all rights reserved.
8 ;; Copyright (C) 2009, Thierry Volpiatto, all rights reserved.
9 ;; Created: Mon Jul 12 13:43:55 2010 (-0700)
10 ;; Last-Updated: Wed May 16 08:20:58 2012 (-0700)
11 ;; By: dradams
12 ;; Update #: 5559
13 ;; URL: http://www.emacswiki.org/cgi-bin/wiki/bookmark+-1.el
14 ;; Keywords: bookmarks, bookmark+, placeholders, annotations, search, info, url, w3m, gnus
15 ;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x
16 ;;
17 ;; Features that might be required by this library:
18 ;;
19 ;; `bookmark', `bookmark+-1', `bookmark+-mac', `cl', `dired',
20 ;; `dired-aux', `dired-x', `ffap', `pp', `thingatpt', `thingatpt+'.
21 ;;
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23 ;;
24 ;;; Commentary:
25 ;;
26 ;; The Bookmark+ libraries are these:
27 ;;
28 ;; `bookmark+.el' - main (driver) library
29 ;; `bookmark+-mac.el' - Lisp macros
30 ;; `bookmark+-lit.el' - (optional) code for highlighting bookmarks
31 ;; `bookmark+-bmu.el' - code for the `*Bookmark List*' (bmenu)
32 ;; `bookmark+-1.el' - other (non-bmenu) required code (this file)
33 ;; `bookmark+-key.el' - key and menu bindings
34 ;;
35 ;; `bookmark+-doc.el' - documentation (comment-only file)
36 ;; `bookmark+-chg.el' - change log (comment-only file)
37 ;;
38 ;; The documentation (in `bookmark+-doc.el') includes how to
39 ;; byte-compile and install Bookmark+. The documentation is also
40 ;; available in these ways:
41 ;;
42 ;; 1. From the bookmark list (`C-x r l'):
43 ;; Use `?' to show the current bookmark-list status and general
44 ;; help, then click link `Doc in Commentary' or link `Doc on the
45 ;; Web'.
46 ;;
47 ;; 2. From the Emacs-Wiki Web site:
48 ;; http://www.emacswiki.org/cgi-bin/wiki/BookmarkPlus.
49 ;;
50 ;; 3. From the Bookmark+ group customization buffer:
51 ;; `M-x customize-group bookmark-plus', then click link
52 ;; `Commentary'.
53 ;;
54 ;; (The commentary links in #1 and #3 work only if you have library
55 ;; `bookmark+-doc.el' in your `load-path'.)
56
57 ;;(@> "Index")
58 ;;
59 ;; Index
60 ;; -----
61 ;;
62 ;; If you have library `linkd.el' and Emacs 22 or later, load
63 ;; `linkd.el' and turn on `linkd-mode' now. It lets you easily
64 ;; navigate around the sections of this doc. Linkd mode will
65 ;; highlight this Index, as well as the cross-references and section
66 ;; headings throughout this file. You can get `linkd.el' here:
67 ;; http://dto.freeshell.org/notebook/Linkd.html.
68 ;;
69 ;; (@> "Things Defined Here")
70 ;; (@> "User Options (Customizable)")
71 ;; (@> "Internal Variables")
72 ;; (@> "Compatibility Code for Older Emacs Versions")
73 ;; (@> "Core Replacements (`bookmark-*' except `bookmark-bmenu-*')")
74 ;; (@> "Bookmark+ Functions (`bmkp-*')")
75 ;; (@> "Search-and-Replace Locations of Marked Bookmarks")
76 ;; (@> "Tags")
77 ;; (@> "Bookmark Predicates")
78 ;; (@> "Filter Functions")
79 ;; (@> "General Utility Functions")
80 ;; (@> "Bookmark Entry Access Functions")
81 ;; (@> "Sorting - General Functions")
82 ;; (@> "Sorting - Commands")
83 ;; (@> "Sorting - General Predicates")
84 ;; (@> "Sorting - File-Name Predicates")
85 ;; (@> "Indirect Bookmarking Functions")
86 ;; (@> "Other Bookmark+ Functions (`bmkp-*')")
87 ;; (@> "Keymaps")
88
89 ;;(@* "Things Defined Here")
90 ;;
91 ;; Things Defined Here
92 ;; -------------------
93 ;;
94 ;; Commands defined here:
95 ;;
96 ;; `bmkp-add-tags', `bmkp-all-tags-jump',
97 ;; `bmkp-all-tags-jump-other-window', `bmkp-all-tags-regexp-jump',
98 ;; `bmkp-all-tags-regexp-jump-other-window',
99 ;; `bmkp-autofile-add-tags', `bmkp-autofile-all-tags-jump',
100 ;; `bmkp-autofile-all-tags-jump-other-window',
101 ;; `bmkp-autofile-all-tags-regexp-jump',
102 ;; `bmkp-autofile-all-tags-regexp-jump-other-window',
103 ;; `bmkp-autofile-jump', `bmkp-autofile-jump-other-window',
104 ;; `bmkp-autofile-remove-tags', `bmkp-autofile-set',
105 ;; `bmkp-autofile-some-tags-jump',
106 ;; `bmkp-autofile-some-tags-jump-other-window',
107 ;; `bmkp-autofile-some-tags-regexp-jump',
108 ;; `bmkp-autofile-some-tags-regexp-jump-other-window',
109 ;; `bmkp-auto-idle-bookmark-mode', `bmkp-autonamed-jump',
110 ;; `bmkp-autonamed-jump-other-window',
111 ;; `bmkp-autonamed-this-buffer-jump',
112 ;; `bmkp-autonamed-this-buffer-jump-other-window',
113 ;; `bmkp-bookmark-a-file' `bmkp-bookmark-file-jump',
114 ;; `bmkp-bookmark-list-jump',
115 ;; `bmkp-choose-navlist-from-bookmark-list',
116 ;; `bmkp-choose-navlist-of-type', `bmkp-compilation-target-set',
117 ;; `bmkp-compilation-target-set-all', `bmkp-copy-tags',
118 ;; `bmkp-crosshairs-highlight', `bmkp-cycle',
119 ;; `bmkp-cycle-autonamed', `bmkp-cycle-autonamed-other-window',
120 ;; `bmkp-cycle-bookmark-list',
121 ;; `bmkp-cycle-bookmark-list-other-window', `bmkp-cycle-desktop',
122 ;; `bmkp-cycle-dired', `bmkp-cycle-dired-other-window',
123 ;; `bmkp-cycle-file', `bmkp-cycle-file-other-window',
124 ;; `bmkp-cycle-gnus', `bmkp-cycle-gnus-other-window',
125 ;; `bmkp-cycle-info', `bmkp-cycle-info-other-window',
126 ;; `bmkp-cycle-lighted', `bmkp-cycle-lighted-other-window',
127 ;; `bmkp-cycle-local-file', `bmkp-cycle-local-file-other-window',
128 ;; `bmkp-cycle-man', `bmkp-cycle-man-other-window',
129 ;; `bmkp-cycle-non-file', `bmkp-cycle-non-file-other-window',
130 ;; `bmkp-cycle-other-window', `bmkp-cycle-remote-file',
131 ;; `bmkp-cycle-remote-file-other-window',
132 ;; `bmkp-cycle-specific-buffers',
133 ;; `bmkp-cycle-specific-buffers-other-window',
134 ;; `bmkp-cycle-specific-files',
135 ;; `bmkp-cycle-specific-files-other-window',
136 ;; `bmkp-cycle-this-buffer', `bmkp-cycle-this-buffer-other-window',
137 ;; `bmkp-cycle-this-file', `bmkp-cycle-this-file/buffer',
138 ;; `bmkp-cycle-this-file/buffer-other-window',
139 ;; `bmkp-cycle-this-file-other-window', `bmkp-cycle-variable-list',
140 ;; `bmkp-cycle-url', `bmkp-cycle-url-other-window',
141 ;; `bmkp-delete-all-autonamed-for-this-buffer',
142 ;; `bmkp-delete-all-temporary-bookmarks', `bmkp-delete-bookmarks',
143 ;; `bmkp-describe-bookmark', `bmkp-describe-bookmark-internals',
144 ;; `bmkp-desktop-change-dir', `bmkp-desktop-delete',
145 ;; `bmkp-desktop-jump', `bmkp-desktop-read', `bmkp-dired-jump',
146 ;; `bmkp-dired-jump-other-window', `bmkp-dired-this-dir-jump',
147 ;; `bmkp-dired-this-dir-jump-other-window',
148 ;; `bmkp-edit-bookmark-name-and-file', `bmkp-edit-bookmark-record',
149 ;; `bmkp-edit-bookmark-record-send',
150 ;; `bmkp-edit-bookmark-records-send', `bmkp-edit-tags',
151 ;; `bmkp-edit-tags-send', `bmkp-empty-file',
152 ;; `bmkp-file-target-set', `bmkp-file-all-tags-jump',
153 ;; `bmkp-file-all-tags-jump-other-window',
154 ;; `bmkp-file-all-tags-regexp-jump',
155 ;; `bmkp-file-all-tags-regexp-jump-other-window', `bmkp-file-jump',
156 ;; `bmkp-file-jump-other-window', `bmkp-file-some-tags-jump',
157 ;; `bmkp-file-some-tags-jump-other-window',
158 ;; `bmkp-file-some-tags-regexp-jump',
159 ;; `bmkp-file-some-tags-regexp-jump-other-window',
160 ;; `bmkp-file-this-dir-all-tags-jump',
161 ;; `bmkp-file-this-dir-all-tags-jump-other-window',
162 ;; `bmkp-file-this-dir-all-tags-regexp-jump',
163 ;; `bmkp-file-this-dir-all-tags-regexp-jump-other-window',
164 ;; `bmkp-file-this-dir-jump',
165 ;; `bmkp-file-this-dir-jump-other-window',
166 ;; `bmkp-file-this-dir-some-tags-jump',
167 ;; `bmkp-file-this-dir-some-tags-jump-other-window',
168 ;; `bmkp-file-this-dir-some-tags-regexp-jump',
169 ;; `bmkp-file-this-dir-some-tags-regexp-jump-other-window',
170 ;; `bmkp-find-file', `bmkp-find-file-other-window',
171 ;; `bmkp-find-file-all-tags',
172 ;; `bmkp-find-file-all-tags-other-window',
173 ;; `bmkp-find-file-all-tags-regexp',
174 ;; `bmkp-find-file-all-tags-regexp-other-window',
175 ;; `bmkp-find-file-some-tags',
176 ;; `bmkp-find-file-some-tags-other-window',
177 ;; `bmkp-find-file-some-tags-regexp',
178 ;; `bmkp-find-file-some-tags-regexp-other-window',
179 ;; `bmkp-global-auto-idle-bookmark-mode' (Emacs 21+),
180 ;; `bmkp-gnus-jump', `bmkp-gnus-jump-other-window',
181 ;; `bmkp-image-jump', `bmkp-image-jump-other-window',
182 ;; `bmkp-info-jump', `bmkp-info-jump-other-window',
183 ;; `bmkp-jump-in-navlist', `bmkp-jump-in-navlist-other-window',
184 ;; `bmkp-jump-to-type', `bmkp-jump-to-type-other-window',
185 ;; `bmkp-list-all-tags', `bmkp-list-defuns-in-commands-file',
186 ;; `bmkp-local-file-jump', `bmkp-local-file-jump-other-window',
187 ;; `bmkp-make-bookmark-savable', `bmkp-make-bookmark-temporary',
188 ;; `bmkp-make-function-bookmark', `bmkp-man-jump',
189 ;; `bmkp-man-jump-other-window', `bmkp-menu-jump-other-window'
190 ;; (Emacs 20, 21), `bmkp-navlist-bmenu-list',
191 ;; `bmkp-next-autonamed-bookmark',
192 ;; `bmkp-next-autonamed-bookmark-repeat', `bmkp-next-bookmark',
193 ;; `bmkp-next-bookmark-list-bookmark',
194 ;; `bmkp-next-bookmark-list-bookmark-repeat',
195 ;; `bmkp-next-bookmark-repeat', `bmkp-next-bookmark-this-buffer',
196 ;; `bmkp-next-bookmark-this-buffer-repeat',
197 ;; `bmkp-next-bookmark-this-file',
198 ;; `bmkp-next-bookmark-this-file/buffer',
199 ;; `bmkp-next-bookmark-this-file/buffer-repeat',
200 ;; `bmkp-next-bookmark-this-file-repeat', `bmkp-next-bookmark-w32',
201 ;; `bmkp-next-bookmark-w32-repeat', `bmkp-next-desktop-bookmark',
202 ;; `bmkp-next-desktop-bookmark-repeat', `bmkp-next-dired-bookmark',
203 ;; `bmkp-next-dired-bookmark-repeat', `bmkp-next-file-bookmark',
204 ;; `bmkp-next-file-bookmark-repeat', `bmkp-next-gnus-bookmark',
205 ;; `bmkp-next-gnus-bookmark-repeat', `bmkp-next-info-bookmark',
206 ;; `bmkp-next-info-bookmark-repeat', `bmkp-next-lighted-bookmark',
207 ;; `bmkp-next-lighted-bookmark-repeat',
208 ;; `bmkp-next-local-file-bookmark',
209 ;; `bmkp-next-local-file-bookmark-repeat',
210 ;; `bmkp-next-man-bookmark', `bmkp-next-man-bookmark-repeat',
211 ;; `bmkp-next-non-file-bookmark',
212 ;; `bmkp-next-non-file-bookmark-repeat',
213 ;; `bmkp-next-remote-file-bookmark',
214 ;; `bmkp-next-remote-file-bookmark-repeat',
215 ;; `bmkp-next-specific-buffers-bookmark',
216 ;; `bmkp-next-specific-buffers-bookmark-repeat',
217 ;; `bmkp-next-specific-files-bookmark',
218 ;; `bmkp-next-specific-files-bookmark-repeat',
219 ;; `bmkp-next-variable-list-bookmark',
220 ;; `bmkp-next-variable-list-bookmark-repeat',
221 ;; `bmkp-next-url-bookmark', `bmkp-next-url-bookmark-repeat',
222 ;; `bmkp-non-file-jump', `bmkp-non-file-jump-other-window',
223 ;; `bmkp-occur-create-autonamed-bookmarks',
224 ;; `bmkp-occur-target-set', `bmkp-occur-target-set-all',
225 ;; `bmkp-paste-add-tags', `bmkp-paste-replace-tags',
226 ;; `bmkp-previous-bookmark', `bmkp-previous-bookmark-repeat',
227 ;; `bmkp-previous-bookmark-this-buffer',
228 ;; `bmkp-previous-bookmark-this-buffer-repeat',
229 ;; `bmkp-previous-bookmark-this-file',
230 ;; `bmkp-previous-bookmark-this-file/buffer',
231 ;; `bmkp-previous-bookmark-this-file/buffer-repeat',
232 ;; `bmkp-previous-bookmark-this-file-repeat',
233 ;; `bmkp-previous-bookmark-w32',
234 ;; `bmkp-previous-bookmark-w32-repeat',
235 ;; `bmkp-purge-notags-autofiles', `bmkp-read-bookmark-for-type',
236 ;; `bmkp-region-jump', `bmkp-region-jump-other-window',
237 ;; `bmkp-remote-file-jump', `bmkp-remote-file-jump-other-window',
238 ;; `bmkp-remove-all-tags', `bmkp-remove-tags',
239 ;; `bmkp-remove-tags-from-all', `bmkp-rename-tag',
240 ;; `bmkp-revert-bookmark-file', `bmkp-save-menu-list-state',
241 ;; `bmkp-send-bug-report', `bmkp-set-autonamed-bookmark',
242 ;; `bmkp-set-autonamed-bookmark-at-line',
243 ;; `bmkp-set-autonamed-regexp-buffer',
244 ;; `bmkp-set-autonamed-regexp-region',
245 ;; `bmkp-set-bookmark-file-bookmark', `bmkp-set-desktop-bookmark',
246 ;; `bmkp-set-restrictions-bookmark', `bmkp-set-tag-value',
247 ;; `bmkp-set-tag-value-for-navlist',
248 ;; `bmkp-set-variable-list-bookmark', `bmkp-some-tags-jump',
249 ;; `bmkp-some-tags-jump-other-window',
250 ;; `bmkp-some-tags-regexp-jump',
251 ;; `bmkp-some-tags-regexp-jump-other-window',
252 ;; `bmkp-specific-buffers-jump',
253 ;; `bmkp-specific-buffers-jump-other-window',
254 ;; `bmkp-specific-files-jump',
255 ;; `bmkp-specific-files-jump-other-window',
256 ;; `bmkp-switch-bookmark-file', `bmkp-switch-bookmark-file-create',
257 ;; `bmkp-switch-to-last-bookmark-file', `bmkp-tag-a-file',
258 ;; `bmkp-temporary-bookmarking-mode', `bmkp-temporary-jump',
259 ;; `bmkp-temporary-jump-other-window',
260 ;; `bmkp-this-buffer-bmenu-list', `bmkp-this-buffer-jump',
261 ;; `bmkp-this-buffer-jump-other-window',
262 ;; `bmkp-this-file-bmenu-list', `bmkp-this-file/buffer-bmenu-list',
263 ;; `bmkp-toggle-autonamed-bookmark-set/delete',
264 ;; `bmkp-toggle-autotemp-on-set',
265 ;; `bmkp-toggle-bookmark-set-refreshes',
266 ;; `bmkp-toggle-saving-bookmark-file',
267 ;; `bmkp-toggle-saving-menu-list-state',
268 ;; `bmkp-toggle-temporary-bookmark',
269 ;; `bmkp-turn-on-auto-idle-bookmark-mode' (Emacs 21+),
270 ;; `bmkp-unomit-all', `bmkp-untag-a-file', `bmkp-url-target-set',
271 ;; `bmkp-url-jump', `bmkp-url-jump-other-window',
272 ;; `bmkp-variable-list-jump', `bmkp-version',
273 ;; `bmkp-w32-browser-jump', `bmkp-w3m-jump',
274 ;; `bmkp-w3m-jump-other-window', `old-bookmark-insert'.
275 ;;
276 ;; User options defined here:
277 ;;
278 ;; `bmkp-auto-idle-bookmark-min-distance',
279 ;; `bmkp-auto-idle-bookmark-mode-delay',
280 ;; `bmkp-auto-idle-bookmark-mode-lighter',
281 ;; `bmkp-auto-idle-bookmark-mode-set-function',
282 ;; `bmkp-autoname-bookmark-function', `bmkp-autoname-format',
283 ;; `bmkp-autotemp-bookmark-predicates',
284 ;; `bmkp-bookmark-name-length-max',
285 ;; `bmkp-count-multi-mods-as-one-flag', `bmkp-crosshairs-flag',
286 ;; `bmkp-default-bookmark-name',
287 ;; `bmkp-default-handlers-for-file-types',
288 ;; `bmkp-desktop-no-save-vars',
289 ;; `bmkp-guess-default-handler-for-file-flag',
290 ;; `bmkp-handle-region-function', `bmkp-incremental-filter-delay',
291 ;; `bmkp-last-as-first-bookmark-file',
292 ;; `bmkp-menu-popup-max-length', `bmkp-other-window-pop-to-flag',
293 ;; `bmkp-prompt-for-tags-flag', `bmkp-region-search-size',
294 ;; `bmkp-save-new-location-flag',
295 ;; `bmkp-sequence-jump-display-function',
296 ;; `bmkp-show-end-of-region', `bmkp-sort-comparer',
297 ;; `bmkp-su-or-sudo-regexp', `bmkp-tags-for-completion',
298 ;; `bmkp-temporary-bookmarking-mode',
299 ;; `bmkp-temporary-bookmarking-mode-hook',
300 ;; `bmkp-temporary-bookmarking-mode-lighter',
301 ;; `bmkp-this-file/buffer-cycle-sort-comparer', `bmkp-use-region',
302 ;; `bmkp-w3m-allow-multi-tabs'.
303 ;;
304 ;; Non-interactive functions defined here:
305 ;;
306 ;; `bmkext-jump-gnus', `bmkext-jump-man', `bmkext-jump-w3m',
307 ;; `bmkext-jump-woman', `bmkp-all-exif-data',
308 ;; `bmkp-all-tags-alist-only', `bmkp-all-tags-regexp-alist-only',
309 ;; `bmkp-alpha-cp', `bmkp-alpha-p', `bmkp-annotated-alist-only',
310 ;; `bmkp-autofile-alist-only', `bmkp-autofile-all-tags-alist-only',
311 ;; `bmkp-autofile-all-tags-regexp-alist-only',
312 ;; `bmkp-autofile-bookmark-p',
313 ;; `bmkp-autofile-some-tags-alist-only',
314 ;; `bmkp-autofile-some-tags-regexp-alist-only',
315 ;; `bmkp-autoname-bookmark-function-default',
316 ;; `bmkp-autonamed-alist-only',
317 ;; `bmkp-autonamed-bookmark-for-buffer-p',
318 ;; `bmkp-autonamed-bookmark-p',
319 ;; `bmkp-autonamed-this-buffer-alist-only',
320 ;; `bmkp-autonamed-this-buffer-bookmark-p',
321 ;; `bmkp-bookmark-creation-cp', `bmkp-bookmark-data-from-record',
322 ;; `bmkp-bookmark-description', `bmkp-bookmark-last-access-cp',
323 ;; `bmkp-bookmark-file-alist-only',
324 ;; `bmkp-bookmark-list-alist-only',
325 ;; `bmkp-bookmark-file-bookmark-p',
326 ;; `bmkp-bookmark-list-bookmark-p', `bmkp-bookmark-name-member',
327 ;; `bmkp-bookmark-record-from-name', `bmkp-bookmark-type',
328 ;; `bmkp-buffer-last-access-cp', `bmkp-buffer-names',
329 ;; `bmkp-compilation-file+line-at', `bmkp-completing-read-1',
330 ;; `bmkp-completing-read-buffer-name',
331 ;; `bmkp-completing-read-file-name', `bmkp-completing-read-lax',
332 ;; `bmkp-cp-not', `bmkp-create-variable-list-bookmark',
333 ;; `bmkp-current-bookmark-list-state', `bmkp-current-sort-order',
334 ;; `bmkp-cycle-1', `bmkp-default-bookmark-file',
335 ;; `bmkp-default-bookmark-name', `bmkp-default-handler-for-file',
336 ;; `bmkp-default-handler-user', `bmkp-delete-autonamed-no-confirm',
337 ;; `bmkp-delete-autonamed-this-buffer-no-confirm',
338 ;; `bmkp-delete-bookmark-name-from-list',
339 ;; `bmkp-delete-temporary-no-confirm', `bmkp-desktop-alist-only',
340 ;; `bmkp-desktop-bookmark-p', `bmkp-desktop-kill',
341 ;; `bmkp-dired-alist-only', `bmkp-dired-bookmark-p',
342 ;; `bmkp-dired-subdirs', `bmkp-dired-this-dir-alist-only',
343 ;; `bmkp-dired-this-dir-bookmark-p',
344 ;; `bmkp-dired-wildcards-bookmark-p',
345 ;; `bmkp-edit-bookmark-record-mode',
346 ;; `bmkp-edit-bookmark-records-mode', `bmkp-edit-tags-mode',
347 ;; `bmkp-end-position-post-context',
348 ;; `bmkp-end-position-pre-context', `bmkp-every',
349 ;; `bmkp-file-alist-only', `bmkp-file-all-tags-alist-only',
350 ;; `bmkp-file-all-tags-regexp-alist-only', `bmkp-file-alpha-cp',
351 ;; `bmkp-file-attribute-0-cp', `bmkp-file-attribute-1-cp',
352 ;; `bmkp-file-attribute-2-cp', `bmkp-file-attribute-3-cp',
353 ;; `bmkp-file-attribute-4-cp', `bmkp-file-attribute-5-cp',
354 ;; `bmkp-file-attribute-6-cp', `bmkp-file-attribute-7-cp',
355 ;; `bmkp-file-attribute-8-cp', `bmkp-file-attribute-9-cp',
356 ;; `bmkp-file-attribute-10-cp', `bmkp-file-attribute-11-cp',
357 ;; `bmkp-file-bookmark-p', `bmkp-file-names', `bmkp-file-remote-p',
358 ;; `bmkp-file-some-tags-alist-only',
359 ;; `bmkp-file-some-tags-regexp-alist-only',
360 ;; `bmkp-file-this-dir-alist-only',
361 ;; `bmkp-file-this-dir-all-tags-alist-only',
362 ;; `bmkp-file-this-dir-all-tags-regexp-alist-only',
363 ;; `bmkp-file-this-dir-bookmark-p',
364 ;; `bmkp-file-this-dir-some-tags-alist-only',
365 ;; `bmkp-file-this-dir-some-tags-regexp-alist-only',
366 ;; `bmkp-flagged-bookmark-p', `bmkp-flagged-cp', `bmkp-float-time',
367 ;; `bmkp-full-tag', `bmkp-function-bookmark-p',
368 ;; `bmkp-get-autofile-bookmark', `bmkp-get-bookmark-in-alist',
369 ;; `bmkp-get-buffer-name', `bmkp-get-end-position',
370 ;; `bmkp-get-tag-value', `bmkp-get-tags', `bmkp-get-visit-time',
371 ;; `bmkp-get-visits-count', `bmkp-gnus-alist-only',
372 ;; `bmkp-gnus-bookmark-p', `bmkp-gnus-cp', `bmkp-goto-position',
373 ;; `bmkp-handle-region-default', `bmkp-handler-cp',
374 ;; `bmkp-handler-pred', `bmkp-has-tag-p', `bmkp-image-alist-only',
375 ;; `bmkp-image-bookmark-p', `bmkp-info-alist-only',
376 ;; `bmkp-info-bookmark-p', `bmkp-info-cp', `bmkp-isearch-bookmarks'
377 ;; (Emacs 23+), `bmkp-isearch-bookmarks-regexp' (Emacs 23+),
378 ;; `bmkp-isearch-next-bookmark-buffer' (Emacs 23+), `bmkp-jump-1',
379 ;; `bmkp-jump-bookmark-file', `bmkp-jump-bookmark-list',
380 ;; `bmkp-jump-desktop', `bmkp-jump-dired', `bmkp-jump-function',
381 ;; `bmkp-jump-gnus', `bmkp-jump-man', `bmkp-jump-sequence',
382 ;; `bmkp-jump-url-browse', `bmkp-jump-variable-list',
383 ;; `bmkp-jump-w3m', `bmkp-jump-w3m-new-session',
384 ;; `bmkp-jump-w3m-only-one-tab', `bmkp-jump-woman',
385 ;; `bmkp-last-specific-buffer-alist-only',
386 ;; `bmkp-last-specific-buffer-p',
387 ;; `bmkp-last-specific-file-alist-only',
388 ;; `bmkp-last-specific-file-p', `bmkp-line-number-at-pos',
389 ;; `bmkp-list-position', `bmkp-local-directory-bookmark-p',
390 ;; `bmkp-local-file-accessed-more-recently-cp',
391 ;; `bmkp-local-file-alist-only', `bmkp-local-file-bookmark-p',
392 ;; `bmkp-local-file-size-cp', `bmkp-local-file-type-cp',
393 ;; `bmkp-local-file-updated-more-recently-cp',
394 ;; `bmkp-make-bookmark-file-record',
395 ;; `bmkp-make-bookmark-list-record', `bmkp-make-desktop-record',
396 ;; `bmkp-make-dired-record', `bmkp-make-gnus-record',
397 ;; `bmkp-make-man-record', `bmkp-make-plain-predicate',
398 ;; `bmkp-make-record-for-target-file',
399 ;; `bmkp-make-url-browse-record', `bmkp-make-variable-list-record',
400 ;; `bmkp-make-w3m-record', `bmkp-make-woman-record' (Emacs 21+),
401 ;; `bmkp-man-alist-only', `bmkp-man-bookmark-p',
402 ;; `bmkp-marked-bookmark-p', `bmkp-marked-bookmarks-only',
403 ;; `bmkp-marked-cp', `bmkp-maybe-save-bookmarks',
404 ;; `bmkp-modified-bookmark-p', `bmkp-modified-cp',
405 ;; `bmkp-msg-about-sort-order', `bmkp-multi-sort',
406 ;; `bmkp-names-same-bookmark-p', `bmkp-non-autonamed-alist-only',
407 ;; `bmkp-non-file-alist-only', `bmkp-non-file-bookmark-p',
408 ;; `bmkp-not-near-other-auto-idle-bmks', `bmkp-omitted-alist-only',
409 ;; `bmkp-orphaned-file-alist-only',
410 ;; `bmkp-orphaned-file-bookmark-p',
411 ;; `bmkp-orphaned-local-file-alist-only',
412 ;; `bmkp-orphaned-local-file-bookmark-p',
413 ;; `bmkp-orphaned-remote-file-alist-only',
414 ;; `bmkp-orphaned-remote-file-bookmark-p',
415 ;; `bmkp-position-after-whitespace',
416 ;; `bmkp-position-before-whitespace', `bmkp-position-cp',
417 ;; `bmkp-position-post-context',
418 ;; `bmkp-position-post-context-region',
419 ;; `bmkp-position-pre-context', `bmkp-position-pre-context-region',
420 ;; `bmkp-printable-p', `bmkp-printable-vars+vals',
421 ;; `bmkp-read-bookmark-file-name', `bmkp-read-tag-completing',
422 ;; `bmkp-read-tags', `bmkp-read-tags-completing',
423 ;; `bmkp-read-variable', `bmkp-read-variables-completing',
424 ;; `bmkp-record-visit', `bmkp-refresh-latest-bookmark-list',
425 ;; `bmkp-refresh-menu-list', `bmkp-refresh/rebuild-menu-list.',
426 ;; `bmkp-regexp-filtered-annotation-alist-only',
427 ;; `bmkp-regexp-filtered-bookmark-name-alist-only',
428 ;; `bmkp-regexp-filtered-file-name-alist-only',
429 ;; `bmkp-regexp-filtered-tags-alist-only',
430 ;; `bmkp-region-alist-only', `bmkp-region-bookmark-p',
431 ;; `bmkp-remote-file-alist-only', `bmkp-remote-file-bookmark-p',
432 ;; `bmkp-remove-dups', `bmkp-remove-if', `bmkp-remove-if-not',
433 ;; `bmkp-remove-omitted',
434 ;; `bmkp-rename-for-marked-and-omitted-lists',
435 ;; `bmkp-repeat-command', `bmkp-replace-existing-bookmark',
436 ;; `bmkp-root-or-sudo-logged-p', `bmkp-same-creation-time-p',
437 ;; `bmkp-same-file-p', `bmkp-save-new-region-location',
438 ;; `bmkp-select-buffer-other-window', `bmkp-sequence-bookmark-p',
439 ;; `bmkp-set-tag-value-for-bookmarks', `bmkp-set-union',
440 ;; `bmkp-some', `bmkp-some-marked-p', `bmkp-some-tags-alist-only',
441 ;; `bmkp-some-tags-regexp-alist-only', `bmkp-some-unmarked-p'
442 ;; `bmkp-sort-omit', `bmkp-sound-jump',
443 ;; `bmkp-specific-buffers-alist-only',
444 ;; `bmkp-specific-files-alist-only',
445 ;; `bmkp-string-less-case-fold-p', `bmkp-tagged-bookmark-p',
446 ;; `bmkp-tagged-cp', `bmkp-tag-name', `bmkp-tags-in-bookmark-file',
447 ;; `bmkp-tags-list', `bmkp-temporary-alist-only',
448 ;; `bmkp-temporary-bookmark-p', `bmkp-this-buffer-alist-only',
449 ;; `bmkp-this-buffer-p', `bmkp-this-file-alist-only',
450 ;; `bmkp-this-file/buffer-alist-only', `bmkp-this-file-p',
451 ;; `bmkp-unmarked-bookmarks-only', `bmkp-upcase',
452 ;; `bmkp-update-autonamed-bookmark', `bmkp-url-alist-only',
453 ;; `bmkp-url-bookmark-p', `bmkp-url-browse-alist-only',
454 ;; `bmkp-url-browse-bookmark-p', `bmkp-url-cp',
455 ;; `bmkp-variable-list-alist-only',
456 ;; `bmkp-variable-list-bookmark-p', `bmkp-visited-more-cp',
457 ;; `bmkp-w3m-alist-only', `bmkp-w3m-bookmark-p', `bmkp-w3m-cp',
458 ;; `bmkp-w3m-set-new-buffer-name'.
459 ;;
460 ;; Internal variables defined here:
461 ;;
462 ;; `bmkp-after-set-hook', `bmkp-autofile-history',
463 ;; `bmkp-auto-idle-bookmark-mode-timer',
464 ;; `bmkp-auto-idle-bookmarks', `bmkp-autonamed-history',
465 ;; `bmkp-autotemp-all-when-set-p', `bmkp-bookmark-file-history',
466 ;; `bmkp-bookmark-list-history', `bmkp-current-bookmark-file',
467 ;; `bmkp-current-nav-bookmark', `bmkp-desktop-history',
468 ;; `bmkp-dired-history', `bmkp-edit-bookmark-record-mode-map',
469 ;; `bmkp-edit-bookmark-records-mode-map',
470 ;; `bmkp-edit-bookmark-records-number', `bmkp-edit-tags-mode-map',
471 ;; `bmkp-file-bookmark-handlers', `bmkp-file-history',
472 ;; `bmkp-gnus-history', `bmkp-image-history', `bmkp-info-history',
473 ;; `bmkp-isearch-bookmarks' (Emacs 23+),
474 ;; `bmkp-jump-display-function', `bmkp-jump-other-window-map',
475 ;; `bmkp-last-bmenu-state-file', `bmkp-last-bookmark-file',
476 ;; `bmkp-last-save-flag-value', `bmkp-last-specific-buffer',
477 ;; `bmkp-last-specific-file', `bmkp-latest-bookmark-alist',
478 ;; `bmkp-local-file-history', `bmkp-man-history',
479 ;; `bmkp-modified-bookmarks', `bmkp-nav-alist',
480 ;; `bmkp-non-file-filename', `bmkp-non-file-history',
481 ;; `bmkp-region-history', `bmkp-remote-file-history',
482 ;; `bmkp-return-buffer', `bmkp-reverse-multi-sort-p',
483 ;; `bmkp-reverse-sort-p', `bmkp-sorted-alist',
484 ;; `bmkp-specific-buffers-history', `bmkp-specific-files-history',
485 ;; `bmkp-tag-history', `bmkp-tags-alist', `bmkp-temporary-history',
486 ;; `bmkp-types-alist', `bmkp-url-history',
487 ;; `bmkp-use-w32-browser-p', `bmkp-variable-list-history',
488 ;; `bmkp-version-number', `bmkp-w3m-history'.
489 ;;
490 ;;
491 ;; ***** NOTE: The following commands defined in `bookmark.el'
492 ;; have been REDEFINED HERE:
493 ;;
494 ;; `bookmark-delete', `bookmark-edit-annotation',
495 ;; `bookmark-edit-annotation-mode', `bookmark-insert',
496 ;; `bookmark-insert-location', `bookmark-jump',
497 ;; `bookmark-jump-other-window', `bookmark-load',
498 ;; `bookmark-relocate', `bookmark-rename', `bookmark-save',
499 ;; `bookmark-send-edited-annotation', `bookmark-set',
500 ;; `bookmark-set-name', `bookmark-yank-word'.
501 ;;
502 ;;
503 ;; ***** NOTE: The following non-interactive functions defined in
504 ;; `bookmark.el' have been REDEFINED HERE:
505 ;;
506 ;; `bookmark--jump-via', `bookmark-alist-from-buffer',
507 ;; `bookmark-all-names', `bookmark-completing-read',
508 ;; `bookmark-default-handler', `bookmark-exit-hook-internal',
509 ;; `bookmark-get-bookmark', `bookmark-get-bookmark-record' (Emacs
510 ;; 20-22), `bookmark-get-handler' (Emacs 20-22),
511 ;; `bookmark-handle-bookmark', `bookmark-jump-noselect' (Emacs
512 ;; 20-22), `bookmark-location', `bookmark-make-record',
513 ;; `bookmark-make-record-default',
514 ;; `bookmark-maybe-load-default-file', `bookmark-prop-get' (Emacs
515 ;; 20-22), `bookmark-prop-set', `bookmark-show-annotation',
516 ;; `bookmark-show-all-annotations', `bookmark-store' (Emacs 20-22),
517 ;; `bookmark-write-file'.
518 ;;
519 ;;
520 ;; ***** NOTE: The following variables defined in `bookmark.el'
521 ;; have been REDEFINED HERE:
522 ;;
523 ;; `bookmark-alist' (doc string only),
524 ;; `bookmark-make-record-function' (Emacs 20-22),
525 ;; `bookmarks-already-loaded' (doc string only).
526 ;;
527 ;;
528 ;; ***** NOTE: The following functions defined in `info.el'
529 ;; have been REDEFINED HERE:
530 ;;
531 ;; `Info-bookmark-jump' (Emacs 20-22), `Info-bookmark-make-record'
532 ;; (Emacs 20-22).
533 ;;
534 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
535 ;;
536 ;; This program is free software; you can redistribute it and/or modify
537 ;; it under the terms of the GNU General Public License as published by
538 ;; the Free Software Foundation; either version 3, or (at your option)
539 ;; any later version.
540 ;;
541 ;; This program is distributed in the hope that it will be useful,
542 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
543 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
544 ;; GNU General Public License for more details.
545 ;;
546 ;; You should have received a copy of the GNU General Public License
547 ;; along with this program; see the file COPYING. If not, write to
548 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
549 ;; Floor, Boston, MA 02110-1301, USA.
550 ;;
551 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
552 ;;
553 ;;; Code:
554
555 ;;;;;;;;;;;;;;;;;;;;;;;
556
557 (unless (fboundp 'file-remote-p) (require 'ffap)) ;; ffap-file-remote-p
558 (eval-when-compile (require 'gnus)) ;; mail-header-id (really in `nnheader.el')
559 (eval-when-compile (require 'gnus-sum)) ;; gnus-summary-article-header
560 (eval-when-compile (require 'cl)) ;; case, multiple-value-bind, typecase (plus, for Emacs 20: dolist)
561
562 (require 'thingatpt+ nil t) ;; (no error if not found):
563 ;; region-or-non-nil-symbol-name-nearest-point, symbol-nearest-point
564
565 (require 'bookmark)
566 ;; bookmark-alist, bookmark-alist-modification-count, bookmark-annotation-name,
567 ;; bookmark-automatically-show-annotations, bookmark-bmenu-bookmark,
568 ;; bookmark-bmenu-surreptitiously-rebuild-list, bookmark-buffer-file-name, bookmark-buffer-name,
569 ;; bookmark-completion-ignore-case, bookmark-current-bookmark, bookmark-default-file,
570 ;; bookmark-edit-annotation, bookmark-get-annotation, bookmark-get-bookmark-record, bookmark-get-filename,
571 ;; bookmark-get-front-context-string, bookmark-get-handler, bookmark-get-position,
572 ;; bookmark-get-rear-context-string, bookmark-import-new-list, bookmark-insert-file-format-version-stamp,
573 ;; bookmark-kill-line, bookmark-make-record, bookmark-maybe-historicize-string,
574 ;; bookmark-maybe-upgrade-file-format, bookmark-menu-popup-paned-menu, bookmark-name-from-full-record,
575 ;; bookmark-name-from-record, bookmark-popup-menu-and-apply-function, bookmark-prop-get, bookmark-save-flag,
576 ;; bookmark-search-size, bookmark-set-annotation, bookmark-set-filename, bookmark-set-position,
577 ;; bookmark-time-to-save-p, bookmark-use-annotations, bookmark-version-control, bookmark-yank-point
578
579
580 ;; Some general Renamings.
581 ;;
582 ;; 1. Fix incompatibility introduced by gratuitous Emacs name change.
583 ;;
584 (cond ((and (fboundp 'bookmark-name-from-record) (not (fboundp 'bookmark-name-from-full-record)))
585 (defalias 'bookmark-name-from-full-record 'bookmark-name-from-record))
586 ((and (fboundp 'bookmark-name-from-full-record) (not (fboundp 'bookmark-name-from-record)))
587 (defalias 'bookmark-name-from-record 'bookmark-name-from-full-record)))
588
589 ;; 2. The vanilla name of the first is misleading, as it returns only the cdr of the record.
590 ;; The second is for consistency.
591 ;;
592 (defalias 'bmkp-bookmark-data-from-record 'bookmark-get-bookmark-record)
593 (defalias 'bmkp-bookmark-name-from-record 'bookmark-name-from-full-record)
594
595
596 (require 'bookmark+-mac)
597 ;; bmkp-define-cycle-command, bmkp-define-file-sort-predicate, bmkp-menu-bar-make-toggle,
598 ;; bmkp-replace-regexp-in-string, bmkp-with-output-to-plain-temp-buffer
599
600 (put 'bmkp-with-output-to-plain-temp-buffer 'common-lisp-indent-function '(4 &body))
601
602 (eval-when-compile (require 'bookmark+-bmu))
603 ;; bmkp-bmenu-before-hide-marked-alist,
604 ;; bmkp-bmenu-before-hide-unmarked-alist, bmkp-bmenu-commands-file,
605 ;; bmkp-bmenu-filter-function, bmkp-bmenu-filter-pattern,
606 ;; bmkp-bmenu-first-time-p, bmkp-flagged-bookmarks, bmkp-bmenu-goto-bookmark-named,
607 ;; bmkp-bmenu-marked-bookmarks, bmkp-bmenu-omitted-bookmarks,
608 ;; bmkp-bmenu-refresh-menu-list, bmkp-bmenu-show-all,
609 ;; bmkp-bmenu-state-file, bmkp-bmenu-title,
610 ;; bmkp-maybe-unpropertize-bookmark-names, bmkp-sort-orders-alist,
611 ;; bookmark-bmenu-toggle-filenames
612
613
614 ;; (eval-when-compile (require 'bookmark+-lit nil t))
615 ;; bmkp-light-bookmark, bmkp-light-bookmarks, bmkp-light-this-buffer
616
617
618 ;; For the redefinition of `bookmark-get-bookmark'.
619 (provide 'bookmark+-1) ; Ensure this library is loaded before we compile it.
620 (require 'bookmark+-1) ; So be sure to put this library in your `load-path' before
621 ; trying to byte-compile it.
622
623 ;;;;;;;;;;;;;;;;;;;;;;;
624
625 ;; Quiet the byte-compiler
626
627 (defvar bmkp-auto-light-when-set) ; Defined in `bookmark+-lit.el'.
628 (defvar bmkp-auto-light-when-jump) ; Defined in `bookmark+-lit.el'.
629 (defvar bmkp-light-priorities) ; Defined in `bookmark+-lit.el'.
630 (defvar bmkp-temporary-bookmarking-mode)
631 (defvar bmkp-global-auto-idle-bookmark-mode)
632 (defvar bookmark-current-point) ; Defined in `bookmark.el', but not in Emacs 23+.
633 (defvar bookmark-edit-annotation-text-func) ; Defined in `bookmark.el'.
634 (defvar bookmark-read-annotation-text-func) ; Defined in `bookmark.el', but not in Emacs 23+.
635 (defvar bookmark-make-record-function) ; Defined in `bookmark.el'.
636 (defvar desktop-basefilename) ; Defined in `desktop.el' (Emacs < 22).
637 (defvar desktop-base-file-name) ; Defined in `desktop.el'.
638 (defvar desktop-buffer-args-list) ; Defined in `desktop.el'.
639 (defvar desktop-delay-hook) ; Defined in `desktop.el'.
640 (defvar desktop-dirname) ; Defined in `desktop.el'.
641 (defvar desktop-file-modtime) ; Defined in `desktop.el'.
642 (defvar desktop-globals-to-save) ; Defined in `desktop.el'.
643 (defvar desktop-save-mode) ; Defined in `desktop.el'.
644 (defvar desktop-save) ; Defined in `desktop.el'.
645 (defvar dired-actual-switches) ; Defined in `dired.el'.
646 (defvar dired-buffers) ; Defined in `dired.el'.
647 (defvar dired-directory) ; Defined in `dired.el'.
648 (defvar dired-guess-shell-case-fold-search) ; Defined in `dired-x.el'.
649 (defvar dired-subdir-alist) ; Defined in `dired.el'.
650 (defvar gnus-article-current) ; Defined in `gnus-sum.el'.
651 (defvar Info-current-node) ; Defined in `info.el'.
652 (defvar Info-current-file) ; Defined in `info.el'.
653 (defvar Man-arguments) ; Defined in `man.el'.
654 (defvar read-file-name-completion-ignore-case) ; Emacs 23+.
655 (defvar last-repeatable-command) ; Defined in `repeat.el'.
656 (defvar w3m-current-title) ; Defined in `w3m.el'.
657 (defvar w3m-current-url) ; Defined in `w3m.el'.
658 (defvar w3m-mode-map) ; Defined in `w3m.el'.
659 (defvar wide-n-restrictions) ; Defined in `wide-n.el'.
660 (defvar woman-last-file-name) ; Defined in `woman.el'.
661
662 ;;(@* "User Options (Customizable)")
663 ;;; User Options (Customizable) --------------------------------------
664
665 ;;;###autoload
666 (defcustom bmkp-auto-idle-bookmark-min-distance 1000
667 "*Minimum number of chars between automatic bookmark positions."
668 :type '(choice
669 (const :tag "No minumum distance" nil)
670 (integer :tag "At least this many chars" :value 1000))
671 :group 'bookmark-plus)
672
673 ;; Emacs 20 only.
674 ;;;###autoload
675 (unless (fboundp 'define-minor-mode)
676 (defcustom bmkp-auto-idle-bookmark-mode nil
677 "*Non-nil means that bookmarks are created periodically automatically.
678 Setting this variable directly does not take effect;
679 use either \\[customize] or command `bmkp-auto-idle-bookmark-mode'."
680 :set (lambda (symbol value) (bmkp-auto-idle-bookmark-mode (if value 1 -1)))
681 :initialize 'custom-initialize-default
682 :type 'boolean :group 'bookmark-plus :require 'bookmark+))
683
684 ;;;###autoload
685 (defcustom bmkp-auto-idle-bookmark-mode-delay 60
686 "*Number of seconds delay before automatically setting a bookmark.
687 Such automatic bookmarking is controlled by
688 `bmkp-temporary-bookmarking-mode'."
689 :type 'integer :group 'bookmark-plus)
690
691 ;;;###autoload
692 (defcustom bmkp-auto-idle-bookmark-mode-lighter " Auto-Bmk"
693 "*Lighter for `bmkp-auto-idle-bookmark-mode'.
694 This string shows in the mode line when `bmkp-auto-idle-bookmark-mode'
695 is enabled. Set this to nil or \"\" if you do not want any lighter."
696 :type 'string :group 'bookmark-plus)
697
698 ;;;###autoload
699 (defcustom bmkp-auto-idle-bookmark-mode-set-function #'bmkp-set-autonamed-bookmark-at-line
700 "*Function used to set an automatic bookmark.
701 Used by `bmkp-temporary-bookmarking-mode'.
702 The default value, `bmkp-set-autonamed-bookmark-at-line', sets an
703 autonamed bookmark at the start of the current line. To bookmark the
704 current position, so you can have more than one automatic bookmark per
705 line, use `bmkp-set-autonamed-bookmark' instead."
706 :type 'function :group 'bookmark-plus)
707
708 ;;;###autoload
709 (defcustom bmkp-autoname-bookmark-function 'bmkp-autoname-bookmark-function-default
710 "*Function to automatically name a bookmark at point (cursor position).
711 It should accept a buffer position as its (first) argument.
712 The name returned should match the application of
713 `bmkp-autoname-format' to the buffer name."
714 :type 'function :group 'bookmark-plus)
715
716 ;;;###autoload
717 (defcustom bmkp-autoname-format (if (> emacs-major-version 21) "^[0-9]\\{9\\} %s" "^[0-9]+ %s")
718 "*Format string to match an autonamed bookmark name.
719 It must have a single `%s' to accept the buffer name."
720 :type 'string :group 'bookmark-plus)
721
722 ;;;###autoload
723 (defcustom bmkp-autotemp-bookmark-predicates '(bmkp-autonamed-bookmark-p
724 bmkp-autonamed-this-buffer-bookmark-p)
725 "*Predicates for bookmarks to be set (created) as temporary bookmarks.
726 Each is typically a type predicate, but it can be any function that
727 accepts as its (first) argument a bookmark or bookmark name.
728 These are the predefined type predicates:
729 `bmkp-autofile-bookmark-p', `bmkp-autonamed-bookmark-for-buffer-p',
730 `bmkp-autonamed-bookmark-p', `bmkp-autonamed-this-buffer-bookmark-p',
731 `bmkp-bookmark-file-bookmark-p', `bmkp-bookmark-list-bookmark-p',
732 `bmkp-desktop-bookmark-p', `bmkp-dired-bookmark-p',
733 `bmkp-dired-this-dir-bookmark-p', `bmkp-file-bookmark-p',
734 `bmkp-file-remote-p', `bmkp-file-this-dir-bookmark-p',
735 `bmkp-function-bookmark-p', `bmkp-gnus-bookmark-p',
736 `bmkp-image-bookmark-p', `bmkp-info-bookmark-p',
737 `bmkp-last-specific-buffer-p', `bmkp-last-specific-file-p',
738 `bmkp-local-directory-bookmark-p', `bmkp-local-file-bookmark-p',
739 `bmkp-man-bookmark-p', `bmkp-non-file-bookmark-p',
740 `bmkp-region-bookmark-p', `bmkp-remote-file-bookmark-p',
741 `bmkp-sequence-bookmark-p', `bmkp-this-buffer-p', `bmkp-this-file-p',
742 `bmkp-url-bookmark-p', `bmkp-url-browse-bookmark-p',
743 `bmkp-variable-list-bookmark-p', `bmkp-w3m-bookmark-p'"
744 :type '(repeat symbol) :group 'bookmark-plus)
745
746 ;;;###autoload
747 (defcustom bmkp-bookmark-name-length-max 70
748 "*Max number of chars for default name for a bookmark with a region."
749 :type 'integer :group 'bookmark-plus)
750
751 ;;;###autoload
752 (defcustom bmkp-count-multi-mods-as-one-flag t
753 "*Non-nil means count multiple modifications as one.
754
755 This is for `bookmark-alist-modification-count'. Non-nil means that
756 when you invoke a command that acts on multiple bookmarks or acts in
757 multiple ways on one bookmark, all of changes together count as only
758 one moficication. That can prevent automatic saving of your bookmark
759 file during the sequence of modifications, so that when the command is
760 done you can choose not to save (i.e., to quit) if you like."
761 :type 'boolean :group 'bookmark-plus)
762
763 ;;;###autoload
764 (defcustom bmkp-crosshairs-flag (> emacs-major-version 21)
765 "*Non-nil means highlight with crosshairs when you visit a bookmark.
766 The highlighting is temporary - until your next action.
767 You need library `crosshairs.el' for this feature, and you need Emacs
768 22 or later.
769
770 NOTE: Crosshairs highlighting is shown in the buffer that is current
771 after jumping. If the bookmarked jumped to does not really have an
772 associated buffer, for example a bookmark with a handler such as
773 `w32-browser' that just invokes a separate, non-Emacs program, then
774 the current buffer after jumping will be the buffer before jumping.
775
776 If you use this option in Lisp code, you will want to add/remove
777 `bmkp-crosshairs-highlight' to/from `bookmark-after-jump-hook'."
778 :set (lambda (sym new-val)
779 (custom-set-default sym new-val)
780 (if (and bmkp-crosshairs-flag (> emacs-major-version 21)
781 (condition-case nil (require 'crosshairs nil t) (error nil)))
782 (add-hook 'bookmark-after-jump-hook 'bmkp-crosshairs-highlight)
783 (remove-hook 'bookmark-after-jump-hook 'bmkp-crosshairs-highlight)))
784 :type 'boolean :group 'bookmark-plus)
785
786 ;;;###autoload
787 (defcustom bmkp-default-bookmark-name 'highlighted
788 "*Default bookmark name preference.
789 In `*Bookmark List*' use the name of the current line's bookmark.
790 Otherwise, if `bookmark+-lit.el' is not loaded then use the name of
791 the last-used bookmark in the current file.
792
793 Otherwise, use this option to determine the default, by preferring one
794 of the following, if available:
795
796 * a highlighted bookmark at point
797 * the last-used bookmark in the current file"
798 :type '(choice
799 (const :tag "Highlighted bookmark at point" highlighted)
800 (const :tag "Last used bookmark in same file" last-used))
801 :group 'bookmark-plus)
802
803
804 ;; We do not use `define-obsolete-variable-alias' so that byte-compilation in older Emacs
805 ;; works for newer Emacs too.
806 (when (fboundp 'defvaralias) ; Emacs 22+
807 (defvaralias 'bmkp-default-handler-associations 'bmkp-default-handlers-for-file-types)
808 (make-obsolete-variable 'bmkp-default-handler-associations 'bmkp-default-handlers-for-file-types
809 "2012-02-27"))
810
811 ;;;###autoload
812 (defcustom bmkp-default-handlers-for-file-types
813 (and (require 'dired-x) ; It in turn requires `dired-aux.el'
814 (eval-when-compile (when (< emacs-major-version 21) (require 'cl))) ;; `dolist', for Emacs 20
815 (let ((assns ()))
816 (dolist (shell-assn dired-guess-shell-alist-user)
817 (push (cons (car shell-assn)
818 `(lambda (bmk)
819 (dired-run-shell-command
820 (dired-shell-stuff-it ,(cadr shell-assn) (list (bookmark-get-filename bmk))
821 nil nil))))
822 assns))
823 assns))
824 "*File associations for bookmark handlers used for indirect bookmarks.
825 Each element of the alist is (REGEXP . COMMAND).
826 REGEXP matches a file name.
827 COMMAND is a sexp that evaluates to either a shell command (a string)
828 or an Emacs function (a symbol or a lambda form). The shell command
829 or Lisp function must accept a file-name argument.
830
831 Example value:
832
833 ((\"\\\\.pdf$\" . \"AcroRd32.exe\") ; Adobe Acrobat Reader
834 (\"\\\\.ps$\" . \"gsview32.exe\") ; Ghostview (PostScript viewer)
835 (\"\\\\.html?$\" . browse-url) ; Use Lisp function `browse-url'
836 (\"\\\\.doc$\" . w32-browser)) ; Use Lisp function `w32-browser'
837
838 When you change this option using Customize, if you want to use a
839 literal string as COMMAND then you must double-quote the text:
840 \"...\". (But do not use double-quotes for the REGEXP.) If you want
841 to use a symbol as COMMAND, just type the symbol name (no quotes).
842
843 This option is used by `bmkp-default-handler-for-file' to determine
844 the default `file-handler' property for a given file bookmark. If a
845 given file name does not match this option, and if
846 `bmkp-guess-default-handler-for-file-flag' is non-nil, then
847 `bmkp-default-handler-for-file' tries to guess a shell command to use
848 in the default handler. For that it uses `dired-guess-default' and
849 \(Emacs 23+ only) mailcap entries, in that order."
850 :type '(alist :key-type
851 regexp :value-type
852 (sexp :tag "Shell command (string) or Emacs function (symbol or lambda form)"))
853 :group 'bookmark-plus)
854
855 ;;;###autoload
856 (defcustom bmkp-desktop-no-save-vars '(search-ring regexp-search-ring kill-ring)
857 "*List of variables not to save when creating a desktop bookmark.
858 They are removed from `desktop-globals-to-save' for the duration of
859 the save (only)."
860 :type '(repeat (variable :tag "Variable")) :group 'bookmark-plus)
861
862 ;;;###autoload
863 (defcustom bmkp-handle-region-function 'bmkp-handle-region-default
864 "*Function to handle a bookmarked region."
865 :type 'function :group 'bookmark-plus)
866
867 ;;;###autoload
868 (defcustom bmkp-incremental-filter-delay (if (boundp 'bookmark-search-delay)
869 bookmark-search-delay
870 0.2)
871 "*Seconds to wait before updating display when filtering bookmarks."
872 :type 'number :group 'bookmark-plus)
873
874 ;; Remove autoload cookie to avoid (void-variable bookmark-default-file) ;;;###autoload
875 (defcustom bmkp-last-as-first-bookmark-file bookmark-default-file
876 "*Whether to use the last-used bookmark file as the first used.
877 If nil then Emacs always uses the value of `bookmark-default-file' as
878 the initial bookmark file, in any given session.
879
880 If non-nil, Emacs uses the last bookmark file you used, in the last
881 Emacs session. If none was recorded then it uses
882 `bookmark-default-file'. The particular non-nil value must be a an
883 absolute file name \(possibly containing `~') - it is not expanded).
884
885 NOTE: A non-nil option value is overwritten by Bookmark+, so that it
886 becomes the last-used bookmark file. A nil value is never
887 overwritten."
888 :type '(choice
889 (const :tag "Use `bookmark-default-file' as initial bookmark file" nil)
890 (file :tag "Use last-used bookmark file as initial bookmark file"
891 :value "~/.emacs.bmk"))
892 :group 'bookmark)
893
894 ;;;###autoload
895 (defcustom bmkp-menu-popup-max-length 20
896 "*Max number of bookmarks for `bookmark-completing-read' to use a menu.
897 When choosing a bookmark from a list of bookmarks using
898 `bookmark-completing-read', this controls whether to use a menu or
899 minibuffer input with completion.
900 If t, then always use a menu.
901 If nil, then never use a menu.
902 If an integer, then use a menu only if there are fewer bookmark
903 choices than the value."
904 :type '(choice
905 (integer :tag "Use a menu if there are fewer bookmark choices than this" 20)
906 (const :tag "Always use a menu to choose a bookmark" t)
907 (const :tag "Never use a menu to choose a bookmark" nil))
908 :group 'bookmark-plus)
909
910 ;;;###autoload
911 (defcustom bmkp-new-bookmark-default-names
912 (let ((fns '((lambda () (let ((ff (function-called-at-point)))
913 (and ff (symbolp ff) (symbol-name ff)))))))
914 (when (fboundp 'region-or-non-nil-symbol-name-nearest-point) ; Defined in `thingatpt+.el'.
915 (push 'region-or-non-nil-symbol-name-nearest-point fns)))
916 "Functions to produce the default name for a new bookmark.
917 \(The default name for an *existing* bookmark is obtained using
918 `bmkp-default-bookmark-name'.)
919
920 The option value is a list of functions that do not require an
921 argument and return a string (or nil). They are invoked in order to
922 produce the default names.
923
924 The following names are also provided, after the names described
925 above: The value of variable `bookmark-current-bookmark' and the
926 return value of function `bookmark-buffer-name', in that order.
927
928 These latter names are the defaults provided by vanilla Emacs
929 `bookmark.el', so if you want the vanilla behavior then set the option
930 value to nil.
931
932 For non-interactive use of a default bookmark name, and for Emacs
933 prior to Emacs 23 even for interactive use, only the first default
934 name is used.
935
936 Some functions you might want to use in the option value:
937
938 * `region-or-non-nil-symbol-name-nearest-point'
939 * (lambda () (let ((ff (function-called-at-point)))
940 (and (symbolp ff) (symbol-name ff))))
941 * (lambda () (let ((vv (variable-at-point))) ; `variable-at-point'
942 (and (symbolp vv) (symbol-name vv)))) ; returns 0 if no var
943 * `word-at-point'
944 * (lambda () (let ((ss (symbol-at-point)))
945 (and ss (symbol-name ss))))
946
947 The first of these is defined in library `thingatpt+.el'. It returns
948 the text in the region, if it is active and not empty. Otherwise it
949 returns the name of the (non-`nil') symbol nearest point, within
950 maximum search distances `near-point-x-distance' (left and right) and
951 `near-point-y-distance' (up and down)."
952 :type '(repeat function) :group 'bookmark-plus)
953
954 ;;;###autoload
955 (defcustom bmkp-other-window-pop-to-flag t
956 "*Non-nil means other-window bookmark jumping uses `pop-to-buffer'.
957 Use nil if you want the vanilla Emacs behavior, which uses
958 `switch-to-buffer-other-window'. That creates a new window even if
959 there is already another window showing the buffer."
960 :type 'boolean :group 'bookmark-plus)
961
962 ;;;###autoload
963 (defcustom bmkp-prompt-for-tags-flag nil
964 "*Non-nil means `bookmark-set' prompts for tags (when called interactively)."
965 :type 'boolean :group 'bookmark-plus)
966
967 ;;;###autoload
968 (defcustom bmkp-region-search-size 40
969 "*Same as `bookmark-search-size', but specialized for bookmark regions."
970 :type 'integer :group 'bookmark-plus)
971
972 ;;;###autoload
973 (defcustom bmkp-save-new-location-flag t
974 "*Non-nil means save automatically relocated bookmarks.
975 If nil, then the new bookmark location is visited, but it is not saved
976 as part of the bookmark definition."
977 :type 'boolean :group 'bookmark-plus)
978
979 ;;;###autoload
980 (defcustom bmkp-sequence-jump-display-function 'pop-to-buffer
981 "*Function used to display the bookmarks in a bookmark sequence."
982 :type 'function :group 'bookmark-plus)
983
984 ;;;###autoload
985 (defcustom bmkp-show-end-of-region t
986 "*Show end of region with `exchange-point-and-mark' when activating a region.
987 If nil show only beginning of region."
988 :type 'boolean :group 'bookmark-plus)
989
990 ;;;###autoload
991 (defcustom bmkp-sort-comparer '((bmkp-info-cp bmkp-gnus-cp bmkp-url-cp bmkp-local-file-type-cp)
992 bmkp-alpha-p) ; This corresponds to `s k'.
993 ;; $$$$$$ An alternative default value: `bmkp-alpha-p', which corresponds to `s n'.
994 "*Predicate or predicates for sorting (comparing) bookmarks.
995 This defines the default sort for bookmarks in the bookmark list.
996
997 Various sorting commands, such as \\<bookmark-bmenu-mode-map>\
998 `\\[bmkp-bmenu-sort-by-bookmark-visit-frequency]', change the value of this
999 option dynamically (but they do not save the changed value).
1000
1001 The value must be one of the following:
1002
1003 * nil, meaning do not sort
1004
1005 * a predicate that takes two bookmarks as args
1006
1007 * a list of the form ((PRED...) FINAL-PRED), where each PRED and
1008 FINAL-PRED are predicates that take two bookmarks as args
1009
1010 If the value is a list of predicates, then each PRED is tried in turn
1011 until one returns a non-nil value. In that case, the result is the
1012 car of that value. If no non-nil value is returned by any PRED, then
1013 FINAL-PRED is used and its value is the result.
1014
1015 Each PRED should return `(t)' for true, `(nil)' for false, or nil for
1016 undecided. A nil value means that the next PRED decides (or
1017 FINAL-PRED, if there is no next PRED).
1018
1019 Thus, a PRED is a special kind of predicate that indicates either a
1020 boolean value (as a singleton list) or \"I cannot decide - let the
1021 next guy else decide\". (Essentially, each PRED is a hook function
1022 that is run using `run-hook-with-args-until-success'.)
1023
1024 Examples:
1025
1026 nil - No sorting.
1027
1028 string-lessp - Single predicate that returns nil or non-nil.
1029
1030 ((p1 p2)) - Two predicates `p1' and `p2', which each return
1031 (t) for true, (nil) for false, or nil for undecided.
1032
1033 ((p1 p2) string-lessp)
1034 - Same as previous, except if both `p1' and `p2' return
1035 nil, then the return value of `string-lessp' is used.
1036
1037 Note that these two values are generally equivalent, in terms of their
1038 effect (*):
1039
1040 ((p1 p2))
1041 ((p1) p2-plain) where p2-plain is (bmkp-make-plain-predicate p2)
1042
1043 Likewise, these three values generally act equivalently (*):
1044
1045 ((p1))
1046 (() p1-plain)
1047 p1-plain where p1-plain is (bmkp-make-plain-predicate p1)
1048
1049 The PRED form lets you easily combine predicates: use `p1' unless it
1050 cannot decide, in which case try `p2', and so on. The value ((p2 p1))
1051 tries the predicates in the opposite order: first `p2', then `p1' if
1052 `p2' returns nil.
1053
1054 Using a single predicate or FINAL-PRED makes it easy to reuse an
1055 existing predicate that returns nil or non-nil.
1056
1057 You can also convert a PRED-type predicate (which returns (t), (nil),
1058 or nil) into an ordinary predicate, by using function
1059 `bmkp-make-plain-predicate'. That lets you reuse elsewhere, as
1060 ordinary predicates, any PRED-type predicates you define.
1061
1062 For example, this defines a plain predicate to compare by URL:
1063 (defalias 'bmkp-url-p (bmkp-make-plain-predicate 'bmkp-url-cp))
1064
1065 Note: As a convention, predefined Bookmark+ PRED-type predicate names
1066 have the suffix `-cp' (for \"component predicate\") instead of `-p'.
1067
1068 --
1069 * If you use `\\[bmkp-reverse-multi-sort-order]', then there is a difference in \
1070 behavior between
1071
1072 (a) using a plain predicate as FINAL-PRED and
1073 (b) using the analogous PRED-type predicate (and no FINAL-PRED).
1074
1075 In the latter case, `\\[bmkp-reverse-multi-sort-order]' affects when the predicate \
1076 is tried and
1077 its return value. See `bmkp-reverse-multi-sort-order'."
1078 :type '(choice
1079 (const :tag "None (do not sort)" nil)
1080 (function :tag "Sorting Predicate")
1081 (list :tag "Sorting Multi-Predicate"
1082 (repeat (function :tag "Component Predicate"))
1083 (choice
1084 (const :tag "None" nil)
1085 (function :tag "Final Predicate"))))
1086 :group 'bookmark-plus)
1087
1088 ;;;###autoload
1089 (defcustom bmkp-su-or-sudo-regexp "\\(/su:\\|/sudo:\\)"
1090 "*Regexp to recognize `su' or `sudo' Tramp bookmarks."
1091 :type 'regexp :group 'bookmark-plus)
1092
1093 ;;;###autoload
1094 (defcustom bmkp-tags-for-completion 'current
1095 "*List of strings used as tags for completion (not an alist).
1096 The tags can be specified here individually or taken from (a) the
1097 current bookmark list or (b) one or more bookmark files or both.
1098
1099 \(In Emacs 20 and 21, you cannot choose (b) when customizing, but if
1100 \(b) was chosen using a later Emacs version then the option value can
1101 still be used in Emacs 20 and 21.)
1102
1103 If a relative file name is specified for a bookmark file then the
1104 current value of `default-directory' is used to find the file."
1105 :type (if (> emacs-major-version 21)
1106 '(choice
1107 (const :tag "From current bookmarks only" current)
1108 (list :tag "From current bookmarks and other sources"
1109 (const :tag "" current)
1110 (repeat :inline t :tag "Additional sources or specific tags"
1111 (choice
1112 (string :tag "Specific tag")
1113 (cons :tag "All tags from a bookmark file"
1114 (const :tag "" bmkfile) (file :must-match t)))))
1115 (repeat :tag "Choose sources or specific tags"
1116 (choice
1117 (string :tag "Specific tag")
1118 (cons :tag "All tags from a bookmark file"
1119 (const :tag "" bmkfile) (file :must-match t)))))
1120 ;; A bug in Emacs 20-21 means we must sacrifice the user choice of current plus other sources.
1121 '(choice
1122 (const :tag "From current bookmarks only" current)
1123 (repeat :tag "Choose sources or specific tags" ; A 2nd Emacs 20-21 bug ignores `:tag' for menu.
1124 (choice
1125 (string :tag "Specific tag")
1126 (cons :tag "All tags from a bookmark file"
1127 (const :tag "" bmkfile) (file :must-match t))))))
1128 :group 'bookmark-plus)
1129
1130 ;; Emacs 20 only.
1131 (unless (fboundp 'define-minor-mode)
1132 (defcustom bmkp-temporary-bookmarking-mode nil
1133 "*Non-nil means that bookmarks are temporary (not recorded on disk).
1134 Setting this variable directly does not take effect;
1135 use either \\[customize] or command `bmkp-temporary-bookmarking-mode'."
1136 :set (lambda (symbol value) (bmkp-temporary-bookmarking-mode (if value 1 -1)))
1137 :initialize 'custom-initialize-default
1138 :type 'boolean :group 'bookmark-plus :require 'bookmark+))
1139
1140 ;;;###autoload
1141 (defcustom bmkp-temporary-bookmarking-mode-hook ()
1142 "*Functions run after entering and exiting temporary-bookmarking mode."
1143 :type 'hook :group 'bookmark-plus)
1144
1145 ;;;###autoload
1146 (defcustom bmkp-this-file/buffer-cycle-sort-comparer '((bmkp-position-cp))
1147 "*`bmkp-sort-comparer' value for cycling this-file/buffer bookmarks.
1148 Use bookmarks for the currently visited file or (non-file) buffer.
1149 Some values you might want to use: ((bmkp-position-cp)),
1150 ((bmkp-bookmark-creation-cp)), ((bmkp-visited-more-cp)).
1151 See `bmkp-sort-comparer'."
1152 :type '(choice
1153 (const :tag "None (do not sort)" nil)
1154 (function :tag "Sorting Predicate")
1155 (list :tag "Sorting Multi-Predicate"
1156 (repeat (function :tag "Component Predicate"))
1157 (choice
1158 (const :tag "None" nil)
1159 (function :tag "Final Predicate"))))
1160 :group 'bookmark-plus)
1161
1162 ;;;###autoload
1163 (defcustom bmkp-guess-default-handler-for-file-flag nil
1164 "*Non-nil means guess the default handler when creating a file bookmark.
1165 This is ignored if a handler can be found using option
1166 `bmkp-default-handlers-for-file-types'. Otherwise, this is used by
1167 function `bmkp-default-handler-for-file' to determine the default
1168 handler for a given file."
1169 :type 'boolean :group 'bookmark-plus)
1170
1171 ;;;###autoload
1172 (defcustom bmkp-temporary-bookmarking-mode-lighter " Temp-Bmk"
1173 "*Lighter for `bmkp-temporary-bookmarking-mode'.
1174 This string shows in the mode line when `bmkp-temporary-bookmarking-mode'
1175 is enabled. Set this to nil or \"\" if you do not want any lighter."
1176 :type 'string :group 'bookmark-plus)
1177
1178 ;;;###autoload
1179 (defcustom bmkp-use-region t
1180 "*Non-nil means visiting a bookmark activates its recorded region."
1181 :type '(choice
1182 (const :tag "Activate bookmark region (except during cycling)" t)
1183 (const :tag "Do not activate bookmark region" nil)
1184 (const :tag "Activate bookmark region even during cycling" cycling-too))
1185 :group 'bookmark-plus)
1186
1187 ;;;###autoload
1188 (defcustom bmkp-w3m-allow-multi-tabs t
1189 "*Non-nil means jump to W3M bookmarks in a new session."
1190 :type 'boolean :group 'bookmark-plus)
1191
1192 ;;(@* "Internal Variables")
1193 ;;; Internal Variables -----------------------------------------------
1194
1195 (defconst bmkp-non-file-filename " - no file -"
1196 "Name to use for `filename' entry, for non-file bookmarks.")
1197
1198 (defconst bmkp-types-alist '(("autofile" . bmkp-autofile-history)
1199 ("autonamed" . bmkp-autonamed-history)
1200 ("bookmark-file" . bmkp-bookmark-file-history)
1201 ("bookmark-list" . bmkp-bookmark-list-history)
1202 ("desktop" . bmkp-desktop-history)
1203 ("dired" . bmkp-dired-history)
1204 ("dired-this-dir" . bmkp-dired-history)
1205 ("file" . bmkp-file-history)
1206 ("file-this-dir" . bmkp-file-history)
1207 ("gnus" . bmkp-gnus-history)
1208 ("image" . bmkp-image-history)
1209 ("info" . bmkp-info-history)
1210 ("local-file" . bmkp-local-file-history)
1211 ("man" . bmkp-man-history)
1212 ("non-file" . bmkp-non-file-history)
1213 ("region" . bmkp-region-history)
1214 ("remote-file" . bmkp-remote-file-history)
1215 ("specific-buffers" . bmkp-specific-buffers-history)
1216 ("specific-files" . bmkp-specific-files-history)
1217 ("temporary" . bmkp-temporary-history)
1218 ("url" . bmkp-url-history)
1219 ("variable-list" . bmkp-variable-list-history))
1220 "Alist of bookmark types used by `bmkp-jump-to-type'.
1221 Keys are bookmark type names. Values are corresponding history variables.")
1222
1223 (defvar bmkp-autofile-history () "History for autofile bookmarks.")
1224 (defvar bmkp-autonamed-history () "History for autonamed bookmarks.")
1225 (defvar bmkp-bookmark-file-history () "History for bookmark-file bookmarks.")
1226 (defvar bmkp-bookmark-list-history () "History for bookmark-list bookmarks.")
1227 (defvar bmkp-desktop-history () "History for desktop bookmarks.")
1228 (defvar bmkp-dired-history () "History for Dired bookmarks.")
1229 (defvar bmkp-file-history () "History for file bookmarks.")
1230 (defvar bmkp-gnus-history () "History for Gnus bookmarks.")
1231 (defvar bmkp-image-history () "History for image-file bookmarks.")
1232 (defvar bmkp-info-history () "History for Info bookmarks.")
1233 (defvar bmkp-last-bmenu-state-file nil "Last value of option `bmkp-bmenu-state-file'.")
1234 (defvar bmkp-local-file-history () "History for local-file bookmarks.")
1235 (defvar bmkp-man-history () "History for `man'-page bookmarks.")
1236 (defvar bmkp-non-file-history () "History for buffer (non-file) bookmarks.")
1237 (defvar bmkp-region-history () "History for bookmarks that activate the region.")
1238 (defvar bmkp-remote-file-history () "History for remote-file bookmarks.")
1239 (defvar bmkp-specific-buffers-history () "History for specific-buffers bookmarks.")
1240 (defvar bmkp-specific-files-history () "History for specific-files bookmarks.")
1241 (defvar bmkp-temporary-history () "History for temporary bookmarks.")
1242 (defvar bmkp-url-history () "History for URL bookmarks.")
1243 (defvar bmkp-variable-list-history () "History for variable-list bookmarks.")
1244 (defvar bmkp-w3m-history () "History for W3M bookmarks.")
1245
1246 (defvar bmkp-after-set-hook nil "Hook run after `bookmark-set' sets a bookmark.")
1247
1248 (defvar bmkp-auto-idle-bookmarks ()
1249 "Alist of bookmarks that were created automatically during this session.")
1250
1251 (defvar bmkp-auto-idle-bookmark-mode-timer nil
1252 "Timer for `bmkp-auto-idle-bookmark-mode'.
1253 This variable is buffer-local, which means that there is a separate
1254 timer for each buffer where automatic bookmarking is enabled.
1255
1256 NOTE: For Emacs 20, the variable is not buffer-local, by default. To
1257 make it so, do this:
1258
1259 (make-variable-buffer-local 'bmkp-auto-idle-bookmark-mode-timer)")
1260
1261 (unless (< emacs-major-version 21) (make-variable-buffer-local 'bmkp-auto-idle-bookmark-mode-timer))
1262
1263
1264 (defvar bmkp-autotemp-all-when-set-p nil "Non-nil means make any bookmark temporary whenever it is set.")
1265
1266 ;;; $$$$$$ No - don't bother.
1267 ;;; (defconst bmkp-bookmark-modifier-functions '(bookmark-prop-set bmkp-replace-existing-bookmark
1268 ;;; bookmark-set-name bookmark-store)
1269 ;;; "List of functions that modify bookmarks.
1270 ;;; Used to mark modified, unsaved bookmarks, in `*Bookmark List*'.
1271 ;;; Should not include any function that calls another in the list.")
1272
1273 (defvar bmkp-copied-tags ()
1274 "List of tags copied from a bookmark, for pasting to other bookmarks.")
1275
1276 (defvar bmkp-current-bookmark-file bookmark-default-file
1277 "Current bookmark file.
1278 When you start Emacs, this is initialized according to
1279 `bmkp-last-as-first-bookmark-file'.
1280
1281 When you load bookmarks using `\\[bmkp-switch-bookmark-file-create]', this is set to the file you
1282 load. When you save bookmarks using `bookmark-save' with no prefix
1283 arg, they are saved to this file.
1284
1285 Loading a bookmark file does not change the value of
1286 `bookmark-default-file', but it might change the value of
1287 `bmkp-last-as-first-bookmark-file' (which see). The value of
1288 `bookmark-default-file' is never changed, except by your
1289 customizations.")
1290
1291 (defvar bmkp-edit-bookmark-orig-record nil
1292 "Record of bookmark being edited.")
1293
1294 (defvar bmkp-file-bookmark-handlers '(bmkp-jump-dired image-bookmark-jump)
1295 "List of functions that handle file or directory bookmarks.
1296 This is used to determine `bmkp-file-bookmark-p'.")
1297
1298 (defvar bmkp-last-bookmark-file bookmark-default-file
1299 "Last bookmark file used in this session (or default bookmark file).
1300 This is a backup for `bmkp-current-bookmark-file'.")
1301
1302 (defvar bmkp-current-nav-bookmark nil "Current bookmark for navigation.")
1303
1304 (defvar bmkp-jump-display-function nil "Function used currently to display a bookmark.")
1305
1306 (defvar bmkp-last-specific-buffer ""
1307 "Name of buffer used by `bmkp-last-specific-buffer-p'.")
1308
1309 (defvar bmkp-last-specific-file ""
1310 "(Absolute) file name used by `bmkp-last-specific-file-p'.")
1311
1312 (defvar bmkp-modified-bookmarks ()
1313 "Alist of bookmarks that have been modified and not saved.")
1314
1315 (defvar bmkp-nav-alist () "Current bookmark alist used for navigation.")
1316
1317 (defvar bmkp-return-buffer nil "Name of buffer to return to.")
1318
1319 (defvar bmkp-reverse-sort-p nil "Non-nil means the sort direction is reversed.")
1320
1321 (defvar bmkp-reverse-multi-sort-p nil
1322 "Non-nil means the truth values returned by predicates are complemented.
1323 This changes the order of the sorting groups, but it does not in
1324 general reverse that order. The order within each group is unchanged
1325 \(not reversed).")
1326
1327 (defvar bmkp-use-w32-browser-p nil
1328 "Non-nil means use `w32-browser' in the default bookmark handler.
1329 That is, use the default Windows application for the bookmarked file.
1330 This has no effect if function `w32-browser' is not defined.")
1331
1332 (defvar bmkp-latest-bookmark-alist () "Copy of `bookmark-alist' as last filtered.")
1333
1334 (defvar bmkp-last-save-flag-value nil "Last value of option `bookmark-save-flag'.")
1335
1336 (defvar bmkp-sorted-alist ()
1337 "Copy of current bookmark alist, as sorted for buffer `*Bookmark List*'.
1338 Has the same structure as `bookmark-alist'.")
1339
1340 (defvar bmkp-tag-history () "History of tags read from the user.")
1341
1342 (defvar bmkp-tags-alist ()
1343 "Alist of all bookmark tags, per option `bmkp-tags-for-completion'.
1344 Each entry is a full tag: a cons whose car is a tag name, a string.
1345 This is set by function `bmkp-tags-list'.
1346 Use that function to update the value.")
1347
1348
1349 ;; REPLACES ORIGINAL DOC STRING in `bookmark.el'.
1350 ;;
1351 ;; Doc string does not say that the file that was loaded is `bookmark-default-file'.
1352 ;;
1353 (defvar bookmarks-already-loaded nil
1354 "Non-nil means some bookmarks have been loaded during this Emacs session.")
1355
1356
1357 ;; REPLACES ORIGINAL DOC STRING in `bookmark.el'.
1358 ;;
1359 ;; Doc string reflects `Bookmark+' enhancements.
1360 ;;
1361 (put 'bookmark-alist 'variable-documentation
1362 "Association list of bookmarks and their records.
1363 Bookmark functions update the value automatically.
1364 You probably do not want to change the value yourself.
1365
1366 The value is an alist with entries of the form
1367 (BOOKMARK-NAME . PARAM-ALIST)
1368 or the deprecated form (BOOKMARK-NAME PARAM-ALIST).
1369
1370 BOOKMARK-NAME is the name you gave to the bookmark when creating it.
1371 PARAM-ALIST is an alist of bookmark information. The order of the
1372 entries in PARAM-ALIST is not important. The possible entries are
1373 described below. An entry with a key but null value means the entry
1374 is not used.
1375
1376 Bookmarks created using vanilla Emacs (`bookmark.el'):
1377
1378 (filename . FILENAME)
1379 (location . LOCATION)
1380 (position . POS)
1381 (front-context-string . STR-AFTER-POS)
1382 (rear-context-string . STR-BEFORE-POS)
1383 (handler . HANDLER)
1384 (annotation . ANNOTATION)
1385
1386 FILENAME names the bookmarked file.
1387 LOCATION names the bookmarked file, URL, or other place (Emacs 23+).
1388 FILENAME or LOCATION is what is shown in the bookmark list
1389 (`C-x r l') when you use `M-t'.
1390 POS is the bookmarked buffer position (position in the file).
1391 STR-AFTER-POS is buffer text that immediately follows POS.
1392 STR-BEFORE-POS is buffer text that immediately precedes POS.
1393 ANNOTATION is a string that you can provide to identify the bookmark.
1394 See options `bookmark-use-annotations' and
1395 `bookmark-automatically-show-annotations'.
1396 HANDLER is a function that provides the bookmark-jump behavior
1397 for a specific kind of bookmark. This is the case for Info
1398 bookmarks, for instance (starting with Emacs 23).
1399
1400 Bookmarks created using Bookmark+ are the same as for vanilla Emacs,
1401 except for the following differences.
1402
1403 1. Visit information is recorded, using entries `visits' and `time':
1404
1405 (visits . NUMBER-OF-VISITS)
1406 (time . TIME-LAST-VISITED)
1407
1408 NUMBER-OF-VISITS is a whole-number counter.
1409
1410 TIME-LAST-VISITED is an Emacs time representation, such as is
1411 returned by function `current-time'.
1412
1413 2. The buffer name is recorded, using entry `buffer-name'. It need
1414 not be associated with a file.
1415
1416 3. If no file is associated with the bookmark, then FILENAME is
1417 ` - no file -'.
1418
1419 4. Bookmarks can be tagged by users. The tag information is recorded
1420 using entry `tags':
1421
1422 (tags . TAGS-ALIST)
1423
1424 TAGS-ALIST is an alist with string keys.
1425
1426 5. A bookmark can be simply a wrapper for a file, in which case it has
1427 entry `file-handler' instead of `handler'. When you \"jump\" to such
1428 a bookmark, the `file-handler' function or shell-command is applied to
1429 the `filename' entry. Any `handler' entry present is ignored, as are
1430 entries such as `position'. It is only the target file that is
1431 important.
1432
1433 6. Bookmarks can have individual highlighting, provided by users.
1434 This overrides any default highlighting.
1435
1436 (lighting . HIGHLIGHTING)
1437
1438 HIGHLIGHTING is a property list that contain any of these keyword
1439 pairs:
1440
1441 `:style' - Highlighting style. Cdrs of `bmkp-light-styles-alist'
1442 entries are the possible values.
1443 `:face' - Highlighting face, a symbol.
1444 `:when' - A sexp to be evaluated. Return value of `:no-light'
1445 means do not highlight.
1446
1447 7. The following additional entries are used to record region
1448 information. When a region is bookmarked, POS represents the region
1449 start position.
1450
1451 (end-position . END-POS)
1452 (front-context-region-string . STR-BEFORE-END-POS)
1453 (rear-context-region-string . STR-AFTER-END-POS))
1454
1455 END-POS is the region end position.
1456 STR-BEFORE-END-POS is buffer text that precedes END-POS.
1457 STR-AFTER-END-POS is buffer text that follows END-POS.
1458
1459 The two context region strings are non-nil only when a region is
1460 bookmarked.
1461
1462 NOTE: The relative locations of `front-context-region-string' and
1463 `rear-context-region-string' are reversed from those of
1464 `front-context-string' and `rear-context-string'. For example,
1465 `front-context-string' is the text that *follows* `position', but
1466 `front-context-region-string' *precedes* `end-position'.
1467
1468 8. The following additional entries are used for a Dired bookmark.
1469
1470 (dired-marked . MARKED-FILES)
1471 (dired-switches . SWITCHES)
1472
1473 MARKED-FILES is the list of files that were marked.
1474 SWITCHES is the string of `dired-listing-switches'.
1475
1476 9. The following additional entries are used for a Gnus bookmark.
1477
1478 (group . GNUS-GROUP-NAME)
1479 (article . GNUS-ARTICLE-NUMBER)
1480 (message-id . GNUS-MESSAGE-ID)
1481
1482 GNUS-GROUP-NAME is the name of a Gnus group.
1483 GNUS-ARTICLE-NUMBER is the number of a Gnus article.
1484 GNUS-MESSAGE-ID is the identifier of a Gnus message.
1485
1486 10. For a URL bookmark, FILENAME or LOCATION is a URL.
1487
1488 11. A sequence bookmark has this additional entry:
1489
1490 (sequence . COMPONENT-BOOKMARKS)
1491
1492 COMPONENT-BOOKMARKS is the list of component bookmark names.
1493
1494 12. A function bookmark has this additional entry, which records the
1495 FUNCTION:
1496
1497 (function . FUNCTION)
1498
1499 13. A bookmark-list bookmark has this additional entry, which records
1500 the state of buffer `*Bookmark List*' at the time it is created:
1501
1502 (bookmark-list . STATE)
1503
1504 STATE records the sort order, filter function, omit list, and title.")
1505
1506 ;;(@* "Compatibility Code for Older Emacs Versions")
1507 ;;; Compatibility Code for Older Emacs Versions ----------------------
1508
1509 (when (< emacs-major-version 23)
1510
1511 ;; These definitions are for Emacs versions prior to Emacs 23.
1512 ;; They are the same as the vanilla Emacs 23+ definitions, except as noted.
1513 ;; They let older versions of Emacs handle bookmarks created with Emacs 23.
1514 ;; (Emacs < 23 also needs a compatible `bookmark-make-record' version,
1515 ;; but I redefine it for all versions, in any case.)
1516
1517 (defun Info-bookmark-make-record ()
1518 "Create an Info bookmark record."
1519 `(,Info-current-node
1520 ,@(bookmark-make-record-default 'no-file)
1521 (filename . ,Info-current-file)
1522 (info-node . ,Info-current-node)
1523 (handler . Info-bookmark-jump)))
1524
1525 ;; Requires `info.el' explicitly (not autoloaded for `Info-find-node'.
1526 (defun Info-bookmark-jump (bookmark)
1527 "Jump to Info bookmark BOOKMARK.
1528 BOOKMARK is a bookmark name or a bookmark record."
1529 (require 'info)
1530 ;; Implements the `handler' for the record type returned by `Info-bookmark-make-record'.
1531 (let* ((file (bookmark-prop-get bookmark 'filename))
1532 (info-node (bookmark-prop-get bookmark 'info-node))
1533 (buf (save-window-excursion ; VANILLA EMACS FIXME: doesn't work with frames!
1534 (Info-find-node file info-node) (current-buffer))))
1535 ;; Use `bookmark-default-handler' to move to appropriate location within Info node.
1536 (bookmark-default-handler
1537 `("" (buffer . ,buf) . ,(bmkp-bookmark-data-from-record bookmark)))))
1538
1539 (add-hook 'Info-mode-hook (lambda () (set (make-local-variable 'bookmark-make-record-function)
1540 'Info-bookmark-make-record)))
1541
1542 (defvar bookmark-make-record-function 'bookmark-make-record-default
1543 "Function called with no arguments, to create a bookmark record.
1544 It should return the new record, which should be a cons cell of the
1545 form (NAME . ALIST) or just ALIST, where ALIST is as described in
1546 `bookmark-alist'. If it cannot construct the record, then it should
1547 raise an error.
1548
1549 NAME is a string that names the new bookmark. NAME can be nil, in
1550 which case a default name is used.
1551
1552 ALIST can contain an entry (handler . FUNCTION) which sets the handler
1553 to FUNCTION, which is then used instead of `bookmark-default-handler'.
1554 FUNCTION must accept the same arguments as `bookmark-default-handler'.
1555
1556 You can set this variable buffer-locally to enable bookmarking of
1557 locations that should be treated specially, such as Info nodes, news
1558 posts, images, pdf documents, etc.")
1559
1560 (defun bookmark-prop-get (bookmark prop)
1561 "Return property PROP of BOOKMARK, or nil if no such property.
1562 BOOKMARK is a bookmark name or a bookmark record."
1563 (cdr (assq prop (bmkp-bookmark-data-from-record bookmark))))
1564
1565 (defun bookmark-get-handler (bookmark)
1566 "Return the `handler' entry for BOOKMARK.
1567 BOOKMARK is a bookmark name or a bookmark record."
1568 (bookmark-prop-get bookmark 'handler))
1569
1570 (defun bookmark-jump-noselect (bookmark)
1571 "Return the location recorded for BOOKMARK.
1572 BOOKMARK is a bookmark name or a bookmark record.
1573 The return value has the form (BUFFER . POINT), where BUFFER is a
1574 buffer and POINT is the location within BUFFER."
1575 (save-excursion (bookmark-handle-bookmark bookmark) (cons (current-buffer) (point)))))
1576
1577 (when (< emacs-major-version 22)
1578
1579 ;; These definitions are for Emacs versions prior to Emacs 22.
1580 ;; They are the same as the vanilla Emacs 22+ definitions, except as noted.
1581
1582 ;;; ;; Bookmark+ doesn't use this, but `bookmark.el' still does. Who has a slow `baud-rate' now?
1583 ;;; (defun bookmark-maybe-message (fmt &rest args)
1584 ;;; "Apply `message' to FMT and ARGS, but only if the display is fast enough."
1585 ;;; (when (>= baud-rate 9600) (apply 'message fmt args)))
1586
1587 ;; Emacs 22+ just uses `bookmark-jump-other-window' for the menu also.
1588 (defun bmkp-menu-jump-other-window (event)
1589 "Jump to BOOKMARK (a point in some file) in another window.
1590 See `bookmark-jump-other-window'."
1591 (interactive "e")
1592 (bookmark-popup-menu-and-apply-function 'bookmark-jump-other-window
1593 "Jump to Bookmark (Other Window)" event)))
1594
1595 ;;(@* "Core Replacements (`bookmark-*' except `bookmark-bmenu-*')")
1596 ;;; Core Replacements (`bookmark-*' except `bookmark-bmenu-*') -------
1597
1598
1599 ;; REPLACES ORIGINAL in `bookmark.el'.
1600 ;;
1601 ;; Doc string does not mention `bookmark-alist': does NOT test whether BOOKMARK is in `bookmark-alist'.
1602 ;;
1603 (defun bookmark-get-bookmark-record (bookmark)
1604 "Return the data part of BOOKMARK, that is, all but the name.
1605 BOOKMARK is a bookmark name or a bookmark record.
1606 If it is a bookmark name then it is looked up in `bookmark-alist'.
1607 If it is a record then it is NOT looked up (need not belong)."
1608 (let ((data (cdr (bookmark-get-bookmark bookmark))))
1609 ;; A bookmark record is either (NAME ALIST) or (NAME . ALIST).
1610 (if (and (null (cdr data)) (consp (caar data)))
1611 (car data)
1612 data)))
1613
1614
1615 ;; REPLACES ORIGINAL in `bookmark.el'.
1616 ;;
1617 ;; 1. If BOOKMARK is a bookmark-name string that has non-nil property `bmkp-full-record'
1618 ;; then look up the bookmark that is the value of that property in `bookmark-alist', and
1619 ;; if found return it.
1620 ;; 2. Handle the should-not-happen case of non-string, non-cons.
1621 ;; 3. Document NOERROR in doc string.
1622 ;;
1623 (defun bookmark-get-bookmark (bookmark &optional noerror)
1624 "Return the full bookmark (record) that corresponds to BOOKMARK.
1625 BOOKMARK is a bookmark name or a bookmark record.
1626 Non-nil optional arg NOERROR means return nil if BOOKMARK is not a
1627 valid bookmark. If NOERROR is nil then raise an error in this case.
1628
1629 If BOOKMARK is a bookmark name instead of a full bookmark then return
1630 what `bmkp-bookmark-record-from-name' (with no MEMP check) returns.
1631
1632 This function is like `bmkp-get-bookmark-in-alist', except that
1633 `bmkp-get-bookmark-in-alist' always tests whether BOOKMARK is in
1634 `bookmark-alist', whether BOOKMARK is a string (a bookmark name) or a
1635 full bookmark. `bmkp-get-bookmark-in-alist' is thus a real test for
1636 bookmark existence. Use `bookmark-get-bookmark' only when you do NOT
1637 want to look up the bookmark in `bookmark-alist'."
1638 (cond ((consp bookmark) bookmark) ; No test of alist membership.
1639 ((stringp bookmark) (bmkp-bookmark-record-from-name bookmark noerror)) ; No MEMP check.
1640 (t (and (not noerror) (error "Invalid bookmark: `%s'" bookmark)))))
1641
1642
1643 ;; REPLACES ORIGINAL in `bookmark.el'.
1644 ;;
1645 ;; Use option `bmkp-new-bookmark-default-names' to obtain the default name.
1646 ;;
1647 (defun bookmark-make-record ()
1648 "Return a new bookmark record (NAME . ALIST) for the current location.
1649 Start with `bookmark-make-record-function'. If it does not provide a
1650 bookmark name, then use option `bmkp-new-bookmark-default-names' to
1651 provide it. If that does not provide it then use
1652 `bookmark-current-bookmark' or `bookmark-buffer-name', in that order."
1653 (let ((record (funcall bookmark-make-record-function))
1654 defname)
1655 (if (stringp (car record))
1656 record
1657 (when (car record) (push nil record))
1658 (setq defname (catch 'bookmark-make-record
1659 (dolist (fn bmkp-new-bookmark-default-names)
1660 (when (functionp fn) ; Be sure it is defined and is a function.
1661 (let ((val (funcall fn)))
1662 (when (and (stringp val) (not (string= "" val)))
1663 (throw 'bookmark-make-record val)))))
1664 (or bookmark-current-bookmark (bookmark-buffer-name))))
1665 (when (and defname (not (stringp defname))) (setq defname (format "%s" defname))) ; Just in case.
1666 (setcar record defname)
1667 record)))
1668
1669
1670 ;; REPLACES ORIGINAL in `bookmark.el'.
1671 ;;
1672 ;; 1. Update the bookmark name also, not just the data, for an existing bookmark.
1673 ;; 2. Use `bmkp-get-bookmark-in-alist' to test whether the bookmark already exists.
1674 ;; 3. Put full bookmark record on bookmark name (inside record) as property `bmkp-full-record'.
1675 ;; 4. Use `bmkp-maybe-save-bookmarks'.
1676 ;; 5. Add the bookmark to `bmkp-modified-bookmarks', and to `bmkp-auto-idle-bookmarks' if appropriate.
1677 ;; 6. Return the bookmark.
1678 ;;
1679 (defun bookmark-store (bookmark-name data no-overwrite &optional no-msg-p)
1680 "Store the bookmark named BOOKMARK-NAME, giving it DATA.
1681 Return the new bookmark.
1682
1683 DATA is the bookmark record without its name, i.e., what
1684 `bmkp-bookmark-data-from-record' returns.
1685
1686 If NO-OVERWRITE is non-nil and bookmark BOOKMARK-NAME already exists
1687 in the current bookmark list (`bookmark-alist') then record the new
1688 bookmark but do not discard the old one.
1689
1690 The check for existence uses `bmkp-get-bookmark-in-alist'.
1691
1692 Note: In spite of the function name, like all functions that define or
1693 change bookmarks, this function does not necessarily save your
1694 bookmark file. Saving the file depends on `bookmark-save-flag'.
1695
1696 Non-nil optional arg NO-MSG-P means do not show progress messages."
1697 (bookmark-maybe-load-default-file)
1698 (let ((bname (copy-sequence bookmark-name))
1699 bmk)
1700 (unless (featurep 'xemacs)
1701 ;; XEmacs's `set-text-properties' does not work on free-standing strings, apparently.
1702 (set-text-properties 0 (length bname) () bname))
1703 (if (or no-overwrite (not (setq bmk (bmkp-get-bookmark-in-alist bname 'NOERROR))))
1704 (push (setq bmk (cons bname data)) bookmark-alist) ; Add new bookmark.
1705 (bookmark-set-name bmk bname) ; Overwrite existing bookmark.
1706 (setcdr bmk data))
1707 ;; Put the full bookmark on its name as property `bmkp-full-record'.
1708 ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
1709 ;; If it needs to be stripped, that will be done when saving.
1710 (put-text-property 0 (length bname) 'bmkp-full-record bmk bname)
1711 (bmkp-maybe-save-bookmarks)
1712 ;; These two are the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
1713 (unless (memq bmk bmkp-modified-bookmarks)
1714 (setq bmkp-modified-bookmarks (cons bmk bmkp-modified-bookmarks)))
1715 (when (and (boundp 'bmkp-setting-auto-idle-bmk-p)
1716 (not (memq bmk bmkp-auto-idle-bookmarks)))
1717 (setq bmkp-auto-idle-bookmarks (cons bmk bmkp-auto-idle-bookmarks)))
1718 (setq bookmark-current-bookmark bname)
1719 (bmkp-refresh/rebuild-menu-list bmk no-msg-p)
1720 bmk)) ; Return the bookmark.
1721
1722
1723 ;; REPLACES ORIGINAL in `bookmark.el'.
1724 ;;
1725 ;; BUG fix: Need bookmark arg in `interactive' spec.
1726 ;;
1727 ;;;###autoload
1728 (defun bookmark-edit-annotation-mode (bookmark)
1729 "Mode for editing the annotation of bookmark BOOKMARK.
1730 When you have finished composing, type \\[bookmark-send-annotation].
1731 BOOKMARK is a bookmark name or a bookmark record.
1732
1733 \\{bookmark-edit-annotation-mode-map}"
1734 (interactive (list (bookmark-completing-read "Edit annotation of bookmark"
1735 (bmkp-default-bookmark-name)
1736 (bmkp-annotated-alist-only))))
1737 (kill-all-local-variables)
1738 (make-local-variable 'bookmark-annotation-name)
1739 (setq bookmark-annotation-name bookmark)
1740 (use-local-map bookmark-edit-annotation-mode-map)
1741 (setq major-mode 'bookmark-edit-annotation-mode
1742 mode-name "Edit Bookmark Annotation")
1743 (insert (funcall (if (boundp 'bookmark-edit-annotation-text-func)
1744 bookmark-edit-annotation-text-func
1745 bookmark-read-annotation-text-func)
1746 bookmark))
1747 (let ((annotation (bookmark-get-annotation bookmark)))
1748 (if (and annotation (not (string-equal annotation "")))
1749 (insert annotation)))
1750 (if (fboundp 'run-mode-hooks)
1751 (run-mode-hooks 'text-mode-hook)
1752 (run-hooks 'text-mode-hook)))
1753
1754
1755 ;; REPLACES ORIGINAL in `bookmark.el'.
1756 ;;
1757 ;; 1. BUG fix: Put point back where it was (on the bookmark just annotated).
1758 ;; 2. Refresh menu list, to pick up the `a' marker.
1759 ;; 3. Make sure it's the annotation buffer that gets killed.
1760 ;; 4. Delete window also, if `misc-cmds.el' loaded.
1761 ;;
1762 ;;;###autoload
1763 (defun bookmark-send-edited-annotation ()
1764 "Use buffer contents as annotation for a bookmark.
1765 Lines beginning with `#' are ignored."
1766 (interactive)
1767 (unless (eq major-mode 'bookmark-edit-annotation-mode)
1768 (error "Not in bookmark-edit-annotation-mode"))
1769 (goto-char (point-min))
1770 (while (< (point) (point-max))
1771 (if (looking-at "^#")
1772 (bookmark-kill-line t)
1773 (forward-line 1)))
1774 (let ((annotation (buffer-substring-no-properties (point-min) (point-max)))
1775 (bookmark bookmark-annotation-name)
1776 (annotation-buf (current-buffer)))
1777 (bookmark-set-annotation bookmark annotation)
1778 (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count))
1779 (bmkp-refresh/rebuild-menu-list bookmark) ; So display `a' and `*' markers (updated).
1780 (if (fboundp 'kill-buffer-and-its-windows)
1781 (kill-buffer-and-its-windows annotation-buf) ; Defined in `misc-cmds.el'.
1782 (kill-buffer annotation-buf))))
1783
1784
1785 ;; REPLACES ORIGINAL in `bookmark.el'.
1786 ;;
1787 ;; Added `interactive' spec.
1788 ;;
1789 ;;;###autoload
1790 (defun bookmark-edit-annotation (bookmark)
1791 "Pop up a buffer for editing bookmark BOOKMARK's annotation.
1792 BOOKMARK is a bookmark name or a bookmark record."
1793 (interactive (list (bookmark-completing-read "Edit annotation of bookmark"
1794 (bmkp-default-bookmark-name)
1795 (bmkp-annotated-alist-only))))
1796 (pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*"))
1797 (bookmark-edit-annotation-mode bookmark))
1798
1799
1800 ;; REPLACES ORIGINAL in `bookmark.el'.
1801 ;;
1802 ;; Added optional arg ALIST.
1803 ;;
1804 (defun bookmark-all-names (&optional alist)
1805 "Return a list of all bookmark names.
1806 The names are those of the bookmarks in ALIST or, if nil,
1807 `bookmark-alist'."
1808 (bookmark-maybe-load-default-file)
1809 (mapcar (lambda (bmk) (bmkp-bookmark-name-from-record bmk)) (or alist bookmark-alist)))
1810
1811
1812 ;; REPLACES ORIGINAL in `bookmark.el'.
1813 ;;
1814 ;; 1. Added optional args ALIST, PRED, and HIST.
1815 ;; 2. Define using helper function `bmkp-completing-read-1',
1816 ;; which binds `icicle-delete-candidate-object' to (essentially) `bookmark-delete'.
1817 ;;
1818 (defun bookmark-completing-read (prompt &optional default alist pred hist)
1819 "Read a bookmark name, prompting with PROMPT.
1820 PROMPT is automatically suffixed with \": \", so do not include that.
1821
1822 Optional arg DEFAULT is a string to return if the user enters the
1823 empty string.
1824 The alist argument used for completion is ALIST or, if nil,
1825 `bookmark-alist'.
1826 Optional arg PRED is a predicate used for completion.
1827 Optional arg HIST is a history variable for completion. Default is
1828 `bookmark-history'.
1829
1830 If you access this function from a menu, then, depending on the value
1831 of option `bmkp-menu-popup-max-length' and the number of
1832 bookmarks in ALIST, you choose the bookmark using a menu or using
1833 completion.
1834
1835 If you use Icicles, then you can use `S-delete' during completion of a
1836 bookmark name to delete the bookmark named by the current completion
1837 candidate."
1838 (bmkp-completing-read-1 prompt default alist pred hist nil))
1839
1840
1841 ;; REPLACES ORIGINAL in `bookmark.el'.
1842 ;;
1843 ;; 1. Handles also regions and non-file buffers.
1844 ;; 2. Do not use NO-CONTEXT or POSN if < Emacs 24.
1845 ;;
1846 (defun bookmark-make-record-default (&optional no-file no-context position visits)
1847 "Return the record describing the location of a new bookmark.
1848 Point must be where the bookmark is to be set.
1849
1850 Non-nil NO-FILE means return only the subset of the record that
1851 pertains to the location within the buffer (not also the file name).
1852
1853 Non-nil NO-CONTEXT means do not include the front and rear context
1854 strings in the record enough.
1855
1856 Non-nil POSITION means record it, not point, as the `position' entry.
1857
1858 Non-nil VISITS means record it as the `visits' entry."
1859 (let* ((dired-p (and (boundp 'dired-buffers) (car (rassq (current-buffer) dired-buffers))))
1860 (buf (buffer-name))
1861 (ctime (current-time))
1862
1863 ;; Begin `let*' dependencies.
1864 (regionp (and transient-mark-mode mark-active (not (eq (mark) (point)))))
1865 (beg (if regionp (region-beginning) (or position (point))))
1866 (end (if regionp (region-end) (point)))
1867 (fcs (if regionp
1868 (bmkp-position-post-context-region beg end)
1869 (bmkp-position-post-context beg)))
1870 (rcs (if regionp
1871 (bmkp-position-pre-context-region beg)
1872 (bmkp-position-pre-context beg)))
1873 (fcrs (when regionp (bmkp-end-position-pre-context beg end)))
1874 (ecrs (when regionp (bmkp-end-position-post-context end))))
1875 `(,@(unless no-file
1876 `((filename . ,(cond ((buffer-file-name) (bookmark-buffer-file-name))
1877 (dired-p nil)
1878 (t bmkp-non-file-filename)))))
1879 (buffer-name . ,buf)
1880 ,@(unless (and no-context (> emacs-major-version 23))
1881 `((front-context-string . ,fcs)))
1882 ,@(unless (and no-context (> emacs-major-version 23))
1883 `((rear-context-string . ,rcs)))
1884 ,@(unless (and no-context (> emacs-major-version 23))
1885 `((front-context-region-string . ,fcrs)))
1886 ,@(unless (and no-context (> emacs-major-version 23))
1887 `((rear-context-region-string . ,ecrs)))
1888 (visits . ,(or visits 0))
1889 (time . ,ctime)
1890 (created . ,ctime)
1891 (position . ,beg)
1892 (end-position . ,end))))
1893
1894
1895 ;; REPLACES ORIGINAL in `bookmark.el'.
1896 ;;
1897 ;; Put full bookmark record on bookmark name (inside record), as property `bmkp-full-record'.
1898 ;;
1899 (defun bookmark-alist-from-buffer ()
1900 "Read and return a bookmark list (in any format) from the current buffer.
1901 Put the full bookmark record on the bookmark name (in the record), as
1902 a text property. Point is irrelevant and unaffected."
1903 (let ((bmks (save-excursion
1904 (goto-char (point-min))
1905 (if (search-forward bookmark-end-of-version-stamp-marker nil t)
1906 (read (current-buffer))
1907 ;; Else we're dealing with format version 0
1908 (if (search-forward "(" nil t)
1909 (progn (forward-char -1) (read (current-buffer)))
1910 ;; Else no hope of getting information here.
1911 (error "Buffer is not in bookmark-list format"))))))
1912 ;; Put full bookmark on bookmark names as property `bmkp-full-record'.
1913 ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
1914 ;; If property needs to be stripped, that will be done when saving.
1915 (dolist (bmk bmks)
1916 (put-text-property 0 (length (car bmk)) 'bmkp-full-record bmk (car bmk)))
1917 bmks))
1918
1919
1920 ;; REPLACES ORIGINAL in `bookmark.el'.
1921 ;;
1922 ;; 1. Use `bookmark-make-record'.
1923 ;; 2. Use special default prompts for active region, W3M, and Gnus.
1924 ;; 3. Use function `bmkp-new-bookmark-default-names', in addition to the name that
1925 ;; `bookmark-make-record' comes up with, as the list of default values.
1926 ;; 4. Use `bmkp-completing-read-lax', choosing from current buffer's bookmarks.
1927 ;; 5. Numeric prefix arg (diff from plain): all bookmarks as completion candidates.
1928 ;; 6. Prompt for tags if `bmkp-prompt-for-tags-flag' is non-nil.
1929 ;; 7. Possibly highlight bookmark and other bookmarks in buffer, per `bmkp-auto-light-when-set'.
1930 ;; 8. Make bookmark temporary, if `bmkp-autotemp-bookmark-predicates' says to.
1931 ;; 9. Run `bmkp-after-set-hook'.
1932 ;;
1933 ;;;###autoload
1934 (defun bookmark-set (&optional name parg interactivep) ; `C-x r m', `C-x p c m'
1935 "Set a bookmark named NAME, then run `bmkp-after-set-hook'.
1936 If the region is active (`transient-mark-mode') and nonempty, then
1937 record the region limits in the bookmark.
1938
1939 If NAME is nil, then prompt for the bookmark name. The default names
1940 for prompting are as follows (in order of priority):
1941
1942 * If in W3M mode, then the current W3M title.
1943
1944 * If in a Gnus mode, then the Gnus summary article header.
1945
1946 * If on a `man' page, then the page name (command and section).
1947
1948 * If the region is active and nonempty, then the buffer name followed
1949 by \": \" and the region prefix (up to
1950 `bmkp-bookmark-name-length-max' chars).
1951
1952 * The names defined by option `bmkp-new-bookmark-default-names'.
1953
1954 * The value of variable `bookmark-current-bookmark', the name of the
1955 last-used bookmark for the current file.
1956
1957 * The value returned by function `bookmark-buffer-name'.
1958
1959 For Emacs 23+, all of the names described above are available as
1960 default values, by repeating `M-n'. For older Emacs versions, the
1961 first name provided is the only default value.
1962
1963 While entering a bookmark name at the prompt:
1964
1965 * You can use (lax) completion against bookmarks in the same buffer.
1966 If there are no bookmarks in the current buffer, then all bookmarks
1967 are completion candidates. (See also below, about a numeric prefix
1968 argument.)
1969
1970 * You can use `C-M-w' to yank words from the buffer to the
1971 minibuffer. Repeating `C-M-w' yanks successive words (newlines
1972 between yanked words are stripped out).
1973
1974 * You can use `C-M-u' to insert the name of the last bookmark used in
1975 the buffer. This can be useful as an aid to track your progress
1976 through a large file. (If no bookmark has yet been used, then
1977 `C-M-u' inserts the name of the visited file.)
1978
1979 A prefix argument changes the behavior as follows:
1980
1981 * Numeric prefix arg: Use all bookmarks as completion candidates,
1982 instead of just the bookmarks for the current buffer.
1983
1984 * Plain prefix arg (`C-u'): Do not overwrite a bookmark that has the
1985 same name as NAME, if such a bookmark already exists. Instead,
1986 push the new bookmark onto the bookmark alist.
1987
1988 The most recently set bookmark named NAME is thus the one in effect
1989 at any given time, but any others named NAME are still available,
1990 should you decide to delete the most recent one.
1991
1992 Use `\\[bookmark-delete]' to remove bookmarks (you give it a name, and it removes
1993 only the first instance of a bookmark with that name from the list of
1994 bookmarks)."
1995 (interactive (list nil current-prefix-arg t))
1996 (unwind-protect
1997 (progn
1998 (bookmark-maybe-load-default-file)
1999 (setq bookmark-current-point (point)) ; `bookmark-current-point' is a free var here.
2000 ;; Do not set these if they are already set in some other buffer (e.g gnus-art).
2001 (unless (and bookmark-yank-point bookmark-current-buffer)
2002 (save-excursion (skip-chars-forward " ") (setq bookmark-yank-point (point)))
2003 (setq bookmark-current-buffer (current-buffer)))
2004 (let* ((record (bookmark-make-record))
2005 (defname (cond ((eq major-mode 'w3m-mode) w3m-current-title)
2006 ((eq major-mode 'gnus-summary-mode) (elt (gnus-summary-article-header) 1))
2007 ((memq major-mode '(Man-mode woman-mode))
2008 (buffer-substring (point-min) (save-excursion (goto-char (point-min))
2009 (skip-syntax-forward "^ ")
2010 (point))))
2011 (t nil)))
2012 (defname (and defname (bmkp-replace-regexp-in-string "\n" " " defname)))
2013 (bname (or name (bmkp-completing-read-lax
2014 "Set bookmark "
2015 (bmkp-new-bookmark-default-names defname)
2016 (and (or (not parg) (consp parg)) ; No numeric PARG: all bookmarks.
2017 (bmkp-specific-buffers-alist-only))
2018 nil 'bookmark-history))))
2019 (when (string-equal bname "") (setq bname defname))
2020 (bookmark-store bname (cdr record) (consp parg) (not interactivep))
2021 (when (and interactivep bmkp-prompt-for-tags-flag)
2022 (bmkp-add-tags bname (bmkp-read-tags-completing) 'NO-UPDATE-P)) ; Do not refresh tags. (?)
2023 (case (and (boundp 'bmkp-auto-light-when-set) bmkp-auto-light-when-set)
2024 (autonamed-bookmark (when (bmkp-autonamed-bookmark-p bname)
2025 (bmkp-light-bookmark bname)))
2026 (non-autonamed-bookmark (unless (bmkp-autonamed-bookmark-p bname)
2027 (bmkp-light-bookmark bname)))
2028 (any-bookmark (bmkp-light-bookmark bname))
2029 (autonamed-in-buffer (bmkp-light-bookmarks
2030 (bmkp-remove-if-not #'bmkp-autonamed-bookmark-p
2031 (bmkp-this-buffer-alist-only))
2032 nil interactivep))
2033 (non-autonamed-in-buffer (bmkp-light-bookmarks
2034 (bmkp-remove-if #'bmkp-autonamed-bookmark-p
2035 (bmkp-this-buffer-alist-only))
2036 nil interactivep))
2037 (all-in-buffer (bmkp-light-this-buffer nil interactivep)))
2038 ;; Maybe make bookmark temporary.
2039 (if bmkp-autotemp-all-when-set-p
2040 (bmkp-make-bookmark-temporary bname)
2041 (catch 'bookmark-set
2042 (dolist (pred bmkp-autotemp-bookmark-predicates)
2043 (when (and (functionp pred) (funcall pred bname))
2044 (bmkp-make-bookmark-temporary bname)
2045 (throw 'bookmark-set t)))))
2046 (run-hooks 'bmkp-after-set-hook)
2047 (if bookmark-use-annotations
2048 (bookmark-edit-annotation bname)
2049 (goto-char bookmark-current-point)))) ; `bookmark-current-point' is a free var here.
2050 (setq bookmark-yank-point nil
2051 bookmark-current-buffer nil)))
2052
2053
2054 ;; REPLACES ORIGINAL in `bookmark.el'.
2055 ;;
2056 ;; Put full bookmark record on the name as property `bmkp-full-record'.
2057 ;; Add BOOKMARK to `bmkp-modified-bookmarks'.
2058 ;;
2059 (defun bookmark-set-name (bookmark newname)
2060 "Set name of BOOKMARK to NEWNAME.
2061 BOOKMARK is a bookmark name or a bookmark record."
2062 (setq bookmark (bookmark-get-bookmark bookmark))
2063 (setcar bookmark newname)
2064 ;; Put the full bookmark on its name as property `bmkp-full-record'.
2065 ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
2066 ;; If it needs to be stripped, that will be done when saving.
2067 (put-text-property 0 (length newname) 'bmkp-full-record bookmark newname)
2068 ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
2069 (unless (memq bookmark bmkp-modified-bookmarks)
2070 (setq bmkp-modified-bookmarks (cons bookmark bmkp-modified-bookmarks))))
2071
2072
2073 ;; REPLACES ORIGINAL in `bookmark.el'.
2074 ;;
2075 ;; Prevent adding a newline in a bookmark name when yanking.
2076 ;;
2077 ;;;###autoload
2078 (defun bookmark-yank-word () ; Bound to `C-M-w' in minibuffer when setting bookmark.
2079 "Yank the word at point in `bookmark-current-buffer'.
2080 Repeat to yank consecutive words from the current buffer, appending
2081 them to the minibuffer. However, newline characters between yanked
2082 words are stripped out."
2083 (interactive)
2084 (let ((string (with-current-buffer bookmark-current-buffer
2085 (goto-char bookmark-yank-point)
2086 (buffer-substring-no-properties (point)
2087 (progn (forward-word 1)
2088 (setq bookmark-yank-point (point)))))))
2089 (setq string (bmkp-replace-regexp-in-string "\n" "" string))
2090 (insert string)))
2091
2092
2093 ;; REPLACES ORIGINAL in `bookmark.el'.
2094 ;;
2095 ;; 1. Separate renaming of obsolete default bookmark name (do it even if not loading the default file).
2096 ;; 2. Load `bmkp-last-as-first-bookmark-file' if it is non-nil.
2097 ;;
2098 (defun bookmark-maybe-load-default-file ()
2099 "If bookmarks have not yet been loaded, load them.
2100 If `bmkp-last-as-first-bookmark-file' is non-nil, load it.
2101 Otherwise, load `bookmark-default-file'."
2102 ;; If there is no file at `bookmark-default-file' but there is a file with the obsolete default
2103 ;; name, then rename that file to the value of `bookmark-default-file'.
2104 ;; Do this regardless of whether it is `bookmark-default-file' that we load here.
2105 (when (and (file-exists-p bookmark-old-default-file) (not (file-exists-p bookmark-default-file)))
2106 (rename-file bookmark-old-default-file bookmark-default-file))
2107 (let ((file-to-load (bmkp-default-bookmark-file)))
2108 (and (not bookmarks-already-loaded)
2109 (null bookmark-alist)
2110 (file-readable-p file-to-load)
2111 (bookmark-load file-to-load t 'nosave)
2112 (setq bookmarks-already-loaded t))))
2113
2114
2115 ;; REPLACES ORIGINAL in `bookmark.el'.
2116 ;;
2117 ;; 1. Save DISPLAY-FUNCTION to `bmkp-jump-display-function' before calling
2118 ;; `bookmark-handle-bookmark'.
2119 ;; 2. Update the name and position of an autonamed bookmark, in case it moved.
2120 ;; 3. Possibly highlight bookmark and other bookmarks in buffer, per `bmkp-auto-light-when-jump'.
2121 ;; 4. Added `catch', so a handler can throw to skip the rest of the processing if it wants.
2122 ;;
2123 (defun bookmark--jump-via (bookmark display-function)
2124 "Display BOOKMARK using DISPLAY-FUNCTION.
2125 Then run `bookmark-after-jump-hook' and show annotations for BOOKMARK.
2126 BOOKMARK is a bookmark name or a bookmark record."
2127 (bmkp-record-visit bookmark 'BATCHP)
2128 (setq bmkp-jump-display-function display-function)
2129 (catch 'bookmark--jump-via
2130 (bookmark-handle-bookmark bookmark)
2131 (let ((win (get-buffer-window (current-buffer) 0)))
2132 (when win (set-window-point win (point))))
2133 ;; If this is an autonamed bookmark, update its name and position, in case it moved.
2134 ;; But don't do this if we're using w32, since we might not have moved to the bookmark position.
2135 (when (and (bmkp-autonamed-bookmark-for-buffer-p bookmark (buffer-name))
2136 (not bmkp-use-w32-browser-p))
2137 (setq bookmark (bmkp-update-autonamed-bookmark bookmark)))
2138 (case (and (boundp 'bmkp-auto-light-when-jump) bmkp-auto-light-when-jump)
2139 (autonamed-bookmark (when (bmkp-autonamed-bookmark-p bookmark)
2140 (bmkp-light-bookmark bookmark nil nil nil 'USE-POINT)))
2141 (non-autonamed-bookmark (unless (bmkp-autonamed-bookmark-p bookmark)
2142 (bmkp-light-bookmark bookmark nil nil nil 'USE-POINT)))
2143 (any-bookmark (bmkp-light-bookmark bookmark nil nil nil 'USE-POINT))
2144 (autonamed-in-buffer (bmkp-light-bookmarks
2145 (bmkp-remove-if-not #'bmkp-autonamed-bookmark-p
2146 (bmkp-this-buffer-alist-only))
2147 nil 'MSG))
2148 (non-autonamed-in-buffer (bmkp-light-bookmarks
2149 (bmkp-remove-if #'bmkp-autonamed-bookmark-p (bmkp-this-buffer-alist-only))
2150 nil 'MSG))
2151 (all-in-buffer (bmkp-light-this-buffer nil 'MSG)))
2152 (let ((orig-buff (current-buffer))) ; Used by `crosshairs-highlight'.
2153 (run-hooks 'bookmark-after-jump-hook))
2154 (let ((jump-fn (bmkp-get-tag-value bookmark "bmkp-jump")))
2155 (when jump-fn (funcall jump-fn)))
2156 (when bookmark-automatically-show-annotations (bookmark-show-annotation bookmark))))
2157
2158
2159 ;; REPLACES ORIGINAL in `bookmark.el'.
2160 ;;
2161 ;; 1. Add to beginning, not end, of bookmark record.
2162 ;; 2. Do not use `nconc'.
2163 ;; 3. Respect both old and newer bookmark formats.
2164 ;; 4. Add BOOKMARK to `bmkp-modified-bookmarks'.
2165 ;;
2166 (defun bookmark-prop-set (bookmark prop val)
2167 "Set the property PROP of BOOKMARK to VAL.
2168 BOOKMARK is a bookmark name or a bookmark record.
2169 If it is a record then it need not belong to `bookmark-alist'."
2170 (let* ((bmk (bookmark-get-bookmark bookmark))
2171 (cell (assq prop (bmkp-bookmark-data-from-record bmk))))
2172 (if cell
2173 (setcdr cell val)
2174 (if (consp (car (cadr bmk))) ; Old format: ("name" ((filename . "f")...))
2175 (setcdr bmk (list (cons (cons prop val) (cadr bmk))))
2176 (setcdr bmk (cons (cons prop val) (cdr bmk))))) ; New: ("name" (filename . "f")...)
2177 ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
2178 (unless (memq bmk bmkp-modified-bookmarks)
2179 (setq bmkp-modified-bookmarks (cons bmk bmkp-modified-bookmarks)))))
2180
2181
2182 ;; REPLACES ORIGINAL in `bookmark.el'.
2183 ;;
2184 ;; 1. Added optional arg USE-REGION-P.
2185 ;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
2186 ;; 3. Use `bmkp-jump-1'.
2187 ;; 4. Added note about Icicles `S-delete' to doc string.
2188 ;;
2189 ;;;###autoload
2190 (defun bookmark-jump (bookmark ; Bound to `C-x j j', `C-x r b', `C-x p g'
2191 &optional display-function use-region-p)
2192 "Jump to bookmark BOOKMARK.
2193 You may have a problem using this function if the value of variable
2194 `bookmark-alist' is nil. If that happens, you need to load in some
2195 bookmarks. See function `bookmark-load' for more about this.
2196
2197 If the file pointed to by BOOKMARK no longer exists, you are asked if
2198 you wish to give the bookmark a new location. If so, `bookmark-jump'
2199 jumps to the new location and saves it.
2200
2201 If the bookmark defines a region, then the region is activated if
2202 `bmkp-use-region' is not-nil or it is nil and you use a prefix
2203 argument. A prefix arg temporarily flips the value of
2204 `bmkp-use-region'.
2205
2206 If you use Icicles, then you can use `S-delete' during completion of a
2207 bookmark name to delete the bookmark named by the current completion
2208 candidate.
2209
2210 In Lisp code:
2211 BOOKMARK is a bookmark name or a bookmark record.
2212 Non-nil DISPLAY-FUNCTION is a function to display the bookmark. By
2213 default, `switch-to-buffer' is used.
2214 Non-nil USE-REGION-P flips the value of `bmkp-use-region'."
2215 (interactive (list (bookmark-completing-read "Jump to bookmark" (bmkp-default-bookmark-name))
2216 nil
2217 current-prefix-arg))
2218 (bmkp-jump-1 bookmark (or display-function 'switch-to-buffer) use-region-p))
2219
2220
2221 ;; REPLACES ORIGINAL in `bookmark.el'.
2222 ;;
2223 ;; 1. Added optional arg USE-REGION-P.
2224 ;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
2225 ;; 3. Use `bmkp-jump-1'.
2226 ;;
2227 ;;;###autoload
2228 (defun bookmark-jump-other-window (bookmark &optional use-region-p)
2229 ; Bound to `C-x 4 j j', `C-x p j', `C-x p o', `C-x p q'
2230 "Jump to bookmark BOOKMARK in another window.
2231 See `bookmark-jump', in particular for info about using a prefix arg."
2232 (interactive (list (bookmark-completing-read "Jump to bookmark (in another window)"
2233 (bmkp-default-bookmark-name))
2234 current-prefix-arg))
2235 (bmkp-jump-1 bookmark 'bmkp-select-buffer-other-window use-region-p))
2236
2237
2238 ;; REPLACES ORIGINAL in `bookmark.el'.
2239 ;;
2240 ;; 1. Privilege property `file-handler' over `handler'. If the former is available, apply it to the file.
2241 ;;
2242 ;; 2. If BOOKMARK has its own handler but that is not a defined function, then use the default handler.
2243 ;; This lets Emacs 22, for instance, handle Emacs 23+ image bookmarks.
2244 ;;
2245 ;; 3. Different relocation message for non-file bookmark.
2246 ;;
2247 (defun bookmark-handle-bookmark (bookmark)
2248 "Call BOOKMARK's handler, or `bookmark-default-handler' if it has none.
2249 Return nil or raise an error.
2250
2251 BOOKMARK is a bookmark name or a bookmark record.
2252
2253 More precisely:
2254
2255 If BOOKMARK has both `file-handler' and `filename' entries then
2256 apply the former to the latter.
2257
2258 Else, if BOOKMARK has a `handler' property that is a defined
2259 function then apply it to BOOKMARK.
2260
2261 Else, apply the default bookmark handler,
2262 `bookmark-default-handler', to BOOKMARK.
2263
2264 The default handler changes the current buffer and point.
2265
2266 If the default handler is used and a file error is raised, the error
2267 is handled as follows:
2268 If BOOKMARK has no `filename' entry, do nothing.
2269 Else prompt to relocate the file.
2270 If relocated, then try again to handle. Else raise a file error."
2271 (cond ((functionp (bookmark-prop-get bookmark 'file-handler))
2272 (funcall (bookmark-prop-get bookmark 'file-handler) (bookmark-get-filename bookmark)))
2273 ((functionp (bookmark-get-handler bookmark))
2274 (funcall (bookmark-get-handler bookmark) (bookmark-get-bookmark bookmark)))
2275 (t
2276 (condition-case err
2277 (funcall 'bookmark-default-handler (bookmark-get-bookmark bookmark))
2278 (bookmark-error-no-filename ; `file-error'
2279 ;; BOOKMARK can be either a bookmark name or a bookmark record.
2280 ;; If a record, do nothing - assume it is a bookmark used internally by some other package.
2281 (when (stringp bookmark)
2282 (let ((file (bookmark-get-filename bookmark))
2283 (use-dialog-box nil)
2284 (use-file-dialog nil))
2285 (when file
2286 ;; Ask user whether to relocate the file. If no, signal the file error.
2287 (unless (string= file bmkp-non-file-filename) (setq file (expand-file-name file)))
2288 (ding)
2289 (cond ((y-or-n-p (if (and (string= file bmkp-non-file-filename)
2290 (bmkp-get-buffer-name bookmark))
2291 "Bookmark's buffer does not exist. Re-create it? "
2292 (concat (file-name-nondirectory file) " nonexistent. Relocate \""
2293 bookmark "\"? ")))
2294 (if (string= file bmkp-non-file-filename)
2295 ;; This is probably not the right way to get the correct buffer, but it's
2296 ;; better than nothing, and it gives the user a chance to DTRT.
2297 (pop-to-buffer (bmkp-get-buffer-name bookmark)) ; Create buffer.
2298 (bookmark-relocate bookmark)) ; Relocate to file.
2299 (funcall (or (bookmark-get-handler bookmark) 'bookmark-default-handler)
2300 (bookmark-get-bookmark bookmark))) ; Try again
2301 (t
2302 (message "Bookmark not relocated: `%s'" bookmark)
2303 (signal (car err) (cdr err)))))))))))
2304 (when (stringp bookmark) (setq bookmark-current-bookmark bookmark))
2305 ;; $$$$$$ The vanilla code returns nil, but there is no explanation of why and no code seems
2306 ;; to use the return value. Perhaps we should return the bookmark instead?
2307 nil) ; Return nil if no error.
2308
2309 (put 'bookmark-error-no-filename 'error-conditions
2310 '(error bookmark-errors bookmark-error-no-filename))
2311 (put 'bookmark-error-no-filename 'error-message "Bookmark has no associated file (or directory)")
2312
2313
2314 ;; REPLACES ORIGINAL in `bookmark.el'.
2315 ;;
2316 ;; 1. Support regions, buffer names, and property `file-handler'.
2317 ;; 2. Handle MS Windows `Open' command if `bmkp-use-w32-browser-p' and if `w32-browser' is defined.
2318 ;;
2319 (defun bookmark-default-handler (bookmark)
2320 "Default handler to jump to the location of BOOKMARK.
2321 Return nil (or raise an error).
2322
2323 BOOKMARK is a bookmark name or a bookmark record.
2324 If it is a record then it need not belong to `bookmark-alist'.
2325
2326 If `bmkp-use-w32-browser-p' is non-nil and function `w32-browser' is
2327 defined, then call `w32-browser'. That is, use the default MS Windows
2328 application for the bookmarked file.
2329
2330 If BOOKMARK has properties `file-handler' and `filename', then apply
2331 the value of the former to the latter.
2332
2333 If BOOKMARK is an old-style Info bookmark, then go to the Info node.
2334
2335 If BOOKMARK records a nonempty region and `bmkp-use-region' is
2336 non-nil then activate the region.
2337
2338 Otherwise, call `bmkp-goto-position' to go to the recorded position."
2339 (let* ((bmk (bookmark-get-bookmark bookmark))
2340 (file (bookmark-get-filename bmk))
2341 (buf (bookmark-prop-get bmk 'buffer))
2342 (bufname (bmkp-get-buffer-name bmk))
2343 (pos (bookmark-get-position bmk))
2344 (end-pos (bmkp-get-end-position bmk))
2345 (old-info-node (and (not (bookmark-get-handler bookmark)) (bookmark-prop-get bmk 'info-node))))
2346
2347 (cond ((and bmkp-use-w32-browser-p (fboundp 'w32-browser) file) (w32-browser file))
2348 ((and (bookmark-prop-get bookmark 'file-handler) file)
2349 (funcall (bookmark-prop-get bookmark 'file-handler) file))
2350 (old-info-node ; Emacs 20-21 Info bookmarks - no handler entry.
2351 (progn (require 'info) (Info-find-node file old-info-node) (goto-char pos)))
2352 ((not (and bmkp-use-region end-pos (/= pos end-pos)))
2353 ;; Single-position bookmark (no region). Go to it.
2354 (bmkp-goto-position bmk file buf bufname pos
2355 (bookmark-get-front-context-string bmk)
2356 (bookmark-get-rear-context-string bmk)))
2357 (t
2358 ;; Bookmark with a region. Go to it and activate the region.
2359 (if (and file (file-readable-p file) (not (buffer-live-p buf)))
2360 (with-current-buffer (find-file-noselect file) (setq buf (buffer-name)))
2361 ;; No file found. If no buffer either, then signal that file doesn't exist.
2362 (unless (or (and buf (get-buffer buf))
2363 (and bufname (get-buffer bufname) (not (string= buf bufname))))
2364 (signal 'bookmark-error-no-filename (list 'stringp file))))
2365 (set-buffer (or buf bufname))
2366 (when bmkp-jump-display-function
2367 (save-current-buffer (funcall bmkp-jump-display-function (current-buffer)))
2368 (raise-frame))
2369 (goto-char (min pos (point-max)))
2370 (when (> pos (point-max)) (error "Bookmark position is beyond buffer end"))
2371 ;; Activate region. Relocate it if it moved. Save relocated bookmark if confirm.
2372 (funcall bmkp-handle-region-function bmk)))
2373 ;; $$$$$$ The vanilla code returns nil, but there is no explanation of why and no code seems
2374 ;; to use the return value. Perhaps we should return the bookmark instead?
2375 nil)) ; Return nil if no file error.
2376
2377
2378 ;; REPLACES ORIGINAL in `bookmark.el'.
2379 ;;
2380 ;; 1. Added bookmark default for interactive use.
2381 ;; 2. Added optional arg NO-UPDATE-P.
2382 ;; 3. Added note about `S-delete' to doc string.
2383 ;; 4. Changed arg name: BOOKMARK -> BOOKMARK-NAME.
2384 ;; 5. Update Dired location too, for Dired bookmark.
2385 ;; 6. Refresh menu list, to show new location.
2386 ;;
2387 ;;;###autoload
2388 (defun bookmark-relocate (bookmark-name &optional no-update-p) ; Not bound
2389 "Relocate the bookmark named BOOKMARK-NAME to another file.
2390 You are prompted for the new file name.
2391
2392 Non-nil NO-UPDATE-P means do not update `bmkp-tags-alist' and do not
2393 refresh/rebuild the bookmark-list display.
2394
2395 Changes the file associated with the bookmark.
2396 Useful when a file has been renamed after a bookmark was set in it.
2397
2398 If you use Icicles, then you can use `S-delete' during completion of a
2399 bookmark name to delete the bookmark named by the current completion
2400 candidate."
2401 (interactive (list (bookmark-completing-read "Bookmark to relocate" (bmkp-default-bookmark-name))))
2402 (bookmark-maybe-historicize-string bookmark-name)
2403 (bookmark-maybe-load-default-file)
2404 (let* ((icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
2405 (bookmark-filename (bookmark-get-filename bookmark-name))
2406 (new-filename (abbreviate-file-name
2407 (expand-file-name
2408 (read-file-name
2409 (format "Relocate %s to: " bookmark-name)
2410 (file-name-directory bookmark-filename))))))
2411 (bookmark-set-filename bookmark-name new-filename)
2412 ;; Change location for Dired too, but not if different from original file name (e.g. a cons).
2413 (let ((dired-dir (bookmark-prop-get bookmark-name 'dired-directory)))
2414 (when (and dired-dir (equal dired-dir bookmark-filename))
2415 (bookmark-prop-set bookmark-name 'dired-directory new-filename))))
2416 (bmkp-maybe-save-bookmarks)
2417 (when (and bookmark-bmenu-toggle-filenames (get-buffer "*Bookmark List*")
2418 (get-buffer-window (get-buffer "*Bookmark List*") 0)
2419 (not no-update-p))
2420 (with-current-buffer (get-buffer "*Bookmark List*") ; Do NOT just use `bmkp-refresh/rebuild-menu-list'.
2421 (bmkp-refresh-menu-list bookmark-name)))) ; So display new location and `*' marker.
2422
2423
2424 ;; REPLACES ORIGINAL in `bookmark.el'.
2425 ;;
2426 ;; 1. Added bookmark default for interactive use.
2427 ;; 2. Do not add any text properties here. That's done in `bmkp-bmenu-propertize-item'.
2428 ;; 3. Added note about `S-delete' to doc string.
2429 ;; 4. Changed arg name: BOOKMARK -> BOOKMARK-NAME.
2430 ;;
2431 ;;;###autoload
2432 (defun bookmark-insert-location (bookmark-name &optional no-history) ; `C-x p I' (original: `C-x p f')
2433 "Insert file or buffer name for the bookmark named BOOKMARK-NAME.
2434 If a file is bookmarked, insert the recorded file name.
2435 If a non-file buffer is bookmarked, insert the recorded buffer name.
2436
2437 Optional second arg NO-HISTORY means do not record this in the
2438 minibuffer history list `bookmark-history'.
2439
2440 If you use Icicles, then you can use `S-delete' during completion of a
2441 bookmark name to delete the bookmark named by the current completion
2442 candidate."
2443 (interactive
2444 (let ((bmk (bookmark-completing-read "Insert bookmark location" (bmkp-default-bookmark-name))))
2445 (if (> emacs-major-version 21) (list bmk) bmk)))
2446 (or no-history (bookmark-maybe-historicize-string bookmark-name))
2447 (insert (bookmark-location bookmark-name))) ; Return the line inserted.
2448
2449
2450 ;; REPLACES ORIGINAL in `bookmark.el'.
2451 ;;
2452 ;; 1. Pass full bookmark to the various "get" functions.
2453 ;; 2. Location returned can be a buffer name, instead of a file name.
2454 ;;
2455 (defun bookmark-location (bookmark)
2456 "Return the name of the file or buffer associated with BOOKMARK.
2457 BOOKMARK is a bookmark name or a bookmark record.
2458 If it is a record then it need not belong to `bookmark-alist'.
2459 Return \"-- Unknown location --\" if no location name can be found."
2460 (bookmark-maybe-load-default-file)
2461 (setq bookmark (bookmark-get-bookmark bookmark))
2462 (or (bookmark-prop-get bookmark 'location)
2463 (bookmark-get-filename bookmark)
2464 (bmkp-get-buffer-name bookmark)
2465 (bookmark-prop-get bookmark 'buffer)
2466 "-- Unknown location --"))
2467 ;; $$$$$$$$$ ""))
2468 ;; $$$$ (error "Bookmark has no file or buffer name: %S" bookmark)))
2469
2470
2471 ;; REPLACES ORIGINAL in `bookmark.el'.
2472 ;;
2473 ;; 1. Added BATCHP arg. Return OLD if BATCHP is non-nil and NEW is nil.
2474 ;; 2. Rename also in marked and omitted lists.
2475 ;; 3. Use `bmkp-bookmark-record-from-name', not `bookmark-get-bookmark'.
2476 ;; 4. Use `bmkp-completing-read-lax', not `read-from-minibuffer'.
2477 ;; 5. Put `bmkp-full-record' property on new name.
2478 ;; 3. Use `bmkp-bookmark-record-from-name', not `bookmark-get-bookmark'.
2479 ;; 4. Added note about `S-delete' to doc string.
2480 ;; 6. Refresh menu list, to show new name.
2481 ;;
2482 ;;;###autoload
2483 (defun bookmark-rename (old &optional new batchp) ; Not bound in Bookmark+
2484 "Change bookmark's name from OLD to NEW.
2485 Interactively:
2486 If called from the keyboard, then prompt for OLD.
2487 If called from the menubar, select OLD from a menu.
2488 If NEW is nil, then prompt for its string value (unless BATCH).
2489
2490 When entering the NEW name you can use completion against existing
2491 bookmark names. This completion is lax, so you can easily edit an
2492 existing name. See `bookmark-set' for particular keys available
2493 during this input.
2494
2495 If BATCHP is non-nil, then do not rebuild the bookmark list. (NEW
2496 should be non-nil if BATCH is non-nil.)
2497
2498 If you use Icicles then you can use `S-delete' during completion of a
2499 bookmark name to delete the bookmark named by the current completion
2500 candidate."
2501 (interactive (list (bookmark-completing-read "Old bookmark name" (bmkp-default-bookmark-name))))
2502 (bookmark-maybe-historicize-string old)
2503 (bookmark-maybe-load-default-file)
2504 (setq bookmark-current-point (point)) ; `bookmark-current-point' is a free var here.
2505 (save-excursion (skip-chars-forward " ") (setq bookmark-yank-point (point)))
2506 (setq bookmark-current-buffer (current-buffer))
2507 (let ((newname (or new (and (not batchp) (bmkp-completing-read-lax "New name: " old)))))
2508 ;;; $$$$$$ (read-from-minibuffer "New name: " nil
2509 ;;; (let ((now-map (copy-keymap minibuffer-local-map)))
2510 ;;; (define-key now-map "\C-w" 'bookmark-yank-word)
2511 ;;; now-map)
2512 ;;; nil 'bookmark-history))))
2513
2514 (when newname
2515 (bookmark-set-name old newname)
2516 ;; Put the bookmark on the name as property `bmkp-full-record'.
2517 ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
2518 ;; If it needs to be stripped, that will be done when saving.
2519 (put-text-property 0 (length newname) 'bmkp-full-record (bmkp-bookmark-record-from-name newname)
2520 newname)
2521 (bmkp-rename-for-marked-and-omitted-lists old newname) ; Rename in marked & omitted lists, if present.
2522 (setq bookmark-current-bookmark newname)
2523 (unless batchp
2524 (if (and (get-buffer "*Bookmark List*") (get-buffer-window (get-buffer "*Bookmark List*") 0))
2525 (with-current-buffer (get-buffer "*Bookmark List*")
2526 (bmkp-refresh-menu-list newname)) ; So the new name is displayed.
2527 (bookmark-bmenu-surreptitiously-rebuild-list)))
2528 (bmkp-maybe-save-bookmarks))
2529 (or newname old))) ; NEWNAME is nil only if BATCHP is non-nil and NEW was nil.
2530
2531
2532 ;; REPLACES ORIGINAL in `bookmark.el'.
2533 ;;
2534 ;; 1. Added bookmark default for interactive use.
2535 ;; 2. Added note about `S-delete' to doc string.
2536 ;; 3. Changed arg name: BOOKMARK -> BOOKMARK-NAME.
2537 ;;
2538 (or (fboundp 'old-bookmark-insert)
2539 (fset 'old-bookmark-insert (symbol-function 'bookmark-insert)))
2540
2541 ;;;###autoload
2542 (defun bookmark-insert (bookmark-name) ; Bound to `C-x p i'
2543 "Insert the text of a bookmarked file.
2544 BOOKMARK-NAME is the name of the bookmark.
2545 You may have a problem using this function if the value of variable
2546 `bookmark-alist' is nil. If that happens, you need to load in some
2547 bookmarks. See function `bookmark-load' for more about this.
2548
2549 If you use Icicles, then you can use `S-delete' during completion of a
2550 bookmark name to delete the bookmark named by the current completion
2551 candidate."
2552 (interactive (list (bookmark-completing-read "Insert bookmark contents" (bmkp-default-bookmark-name))))
2553 (old-bookmark-insert bookmark-name))
2554
2555
2556 ;; REPLACES ORIGINAL in `bookmark.el'.
2557 ;;
2558 ;; 1. Accept a bookmark or a bookmark name as arg.
2559 ;; 2. Use `bmkp-default-bookmark-name' as default when interactive.
2560 ;; 3. Use `bmkp-get-bookmark-in-alist', not `bookmark-get-bookmark'.
2561 ;; 4. Remove highlighting for the bookmark.
2562 ;; 5. Doc string includes note about `S-delete' for Icicles.
2563 ;; 6. Update `bmkp-latest-bookmark-alist', `bmkp-bmenu-omitted-bookmarks', and `bmkp-auto-idle-bookmarks'.
2564 ;; 7. Increment `bookmark-alist-modification-count' even when BATCHP is non-nil.
2565 ;;
2566 ;;;###autoload
2567 (defun bookmark-delete (bookmark &optional batchp) ; Bound to `C-x p d'
2568 "Delete the BOOKMARK from the bookmark list.
2569 BOOKMARK is a bookmark name or a bookmark record.
2570 Interactively, default to the \"current\" bookmark (that is, the one
2571 most recently used in this file), if it exists.
2572
2573 If BOOKMARK is a name and it has property `bmkp-full-record' then use
2574 that property along with the name to find the bookmark to delete.
2575 If it is a name without property `bmkp-full-record' then delete (only)
2576 the first bookmark in `bookmark-alist' with that name.
2577
2578 Optional arg BATCHP means do not update buffer `*Bookmark List*'.
2579
2580 If you use Icicles, then you can use `S-delete' during completion of a
2581 bookmark name to delete the bookmark named by the current completion
2582 candidate. In this way, you can delete multiple bookmarks."
2583 (interactive (list (bookmark-completing-read "Delete bookmark" (bmkp-default-bookmark-name))))
2584
2585 ;; $$$$$$ Instead of loading unconditionally, maybe we should just try to delete conditionally?
2586 ;; IOW, why not (when bookmarks-already-loaded BODY) instead of `bookmark-maybe-load-default-file'?
2587 ;; If it gets called on a hook that gets run before ever loading, then should probably do nothing.
2588 ;; Leaving it as is for now (2011-04-06).
2589 (bookmark-maybe-load-default-file)
2590
2591 (let* ((bmk (bookmark-get-bookmark bookmark 'NOERROR))
2592 (bname (bmkp-bookmark-name-from-record bmk))) ; BOOKMARK might have been a bookmark.
2593 (when bname ; Do nothing if BOOKMARK does not represent a bookmark.
2594 (bookmark-maybe-historicize-string bname)
2595 (when (fboundp 'bmkp-unlight-bookmark) (bmkp-unlight-bookmark bmk 'NOERROR))
2596 (setq bookmark-alist (delq bmk bookmark-alist)
2597 bmkp-latest-bookmark-alist (delq bmk bmkp-latest-bookmark-alist)
2598 bmkp-auto-idle-bookmarks (delq bmk bmkp-auto-idle-bookmarks)
2599 bmkp-bmenu-omitted-bookmarks (bmkp-delete-bookmark-name-from-list
2600 bname bmkp-bmenu-omitted-bookmarks))
2601 (unless (bmkp-get-bookmark-in-alist bookmark-current-bookmark 'NOERROR)
2602 (setq bookmark-current-bookmark nil)) ; Make this nil if last occurrence of BMK was deleted.
2603 ;; Do NOT refresh/rebuild if BATCHP. Caller must do that if batching deletions.
2604 (unless batchp (bmkp-refresh/rebuild-menu-list nil batchp))
2605 (bmkp-maybe-save-bookmarks)))) ; Increments `bookmark-alist-modification-count'.
2606
2607
2608 ;; REPLACES ORIGINAL in `bookmark.el'.
2609 ;;
2610 ;; 1. Use `bmkp-current-bookmark-file', not `bookmark-default-file'.
2611 ;; 2. Update `bmkp-last-as-first-bookmark-file' if it is non-nil.
2612 ;; 3. Reset `bmkp-modified-bookmarks' to ().
2613 ;; 4. Call `bmkp-refresh/rebuild-menu-list'.
2614 ;;
2615 ;;;###autoload
2616 (defun bookmark-save (&optional parg file) ; Bound to `C-x p s'
2617 "Save currently defined bookmarks.
2618 Save by default in the file named by variable
2619 `bmkp-current-bookmark-file'. With a prefix arg, you are prompted for
2620 the file to save to.
2621
2622 If `bmkp-last-as-first-bookmark-file' is non-nil, update its value to
2623 the file being saved.
2624
2625 To load bookmarks from a specific file, use `\\[bookmark-load]'
2626 \(`bookmark-load').
2627
2628 If called from Lisp:
2629 With nil PARG, use file `bmkp-current-bookmark-file'.
2630 With non-nil PARG and non-nil FILE, use file FILE.
2631 With non-nil PARG and nil FILE, prompt the user for the file to use."
2632 (interactive "P")
2633 (bookmark-maybe-load-default-file)
2634 (let ((file-to-save
2635 (cond ((and (not parg) (not file)) bmkp-current-bookmark-file)
2636 ((and (not parg) file) file)
2637 ((and parg (not file)) (bmkp-read-bookmark-file-name "File to save bookmarks in: ")))))
2638 (when (and bmkp-last-as-first-bookmark-file
2639 bookmark-save-flag) ; nil if temporary bookmarking mode.
2640 (customize-save-variable 'bmkp-last-as-first-bookmark-file file-to-save))
2641 (bookmark-write-file file-to-save))
2642 ;; Indicate by the count that we have synced the current bookmark file.
2643 ;; If an error has already occurred somewhere, the count will not be set, which is what we want.
2644 (setq bookmark-alist-modification-count 0
2645 bmkp-modified-bookmarks ())
2646 (bmkp-refresh/rebuild-menu-list))
2647
2648
2649 ;; REPLACES ORIGINAL in `bookmark.el'.
2650 ;;
2651 ;; 1. Do not save temporary bookmarks (`bmkp-temporary-bookmark-p').
2652 ;; 2. Added optional arg ALT-MSG.
2653 ;; 3. Insert code piecewise, to improve performance when saving `bookmark-alist'.
2654 ;; (Do not let `pp' parse all of `bookmark-alist' at once.)
2655 ;; 4. Unless `bmkp-propertize-bookmark-names-flag', remove text properties from bookmark name and file name.
2656 ;; 5. Bind `print-circle' to t around pp, to record bookmark name with `bmkp-full-record' property.
2657 ;; 6. Use `case', not `cond'.
2658 ;;
2659 (defun bookmark-write-file (file &optional alt-msg)
2660 "Write `bookmark-alist' to FILE.
2661 Bookmarks that have a non-nil `bmkp-temp' property are not saved.
2662 They are removed from the bookmark file, but not from the current
2663 bookmark list.
2664
2665 Non-nil ALT-MSG is a message format string to use in place of the
2666 default, \"Saving bookmarks to file `%s'...\". The string must
2667 contain a `%s' construct, so that it can be passed along with FILE to
2668 `format'. At the end, \"done\" is appended to the message."
2669 (let ((msg (or alt-msg "Saving bookmarks to file `%s'..." file)))
2670 (message (or alt-msg "Saving bookmarks to file `%s'...") file)
2671 (with-current-buffer (get-buffer-create " *Bookmarks*")
2672 (goto-char (point-min))
2673 (delete-region (point-min) (point-max))
2674 (let ((print-length nil)
2675 (print-level nil)
2676 bname fname last-fname)
2677 (bookmark-insert-file-format-version-stamp)
2678 (insert "(")
2679 (dolist (bmk bookmark-alist)
2680 (unless (bmkp-temporary-bookmark-p bmk)
2681 (setq bname (car bmk)
2682 fname (bookmark-get-filename bmk))
2683 (when (or (not (> emacs-major-version 20)) ; Emacs 20 can't do (not (boundp 'print-circle)).
2684 (not bmkp-propertize-bookmark-names-flag))
2685 (set-text-properties 0 (length bname) () bname)
2686 (when fname (set-text-properties 0 (length fname) () fname)))
2687 (setcar bmk bname)
2688 (when (setq last-fname (assq 'filename bmk)) (setcdr last-fname fname))
2689 (let ((print-circle t)) (pp bmk (current-buffer)))))
2690 (insert ")")
2691 (let ((version-control (case bookmark-version-control
2692 ((nil) nil)
2693 (never 'never)
2694 (nospecial version-control)
2695 (t t)))
2696 (errorp nil))
2697 (condition-case nil
2698 (write-region (point-min) (point-max) file)
2699 (file-error (setq errorp t) (message "CANNOT WRITE FILE `%s'" file) (sit-for 4)))
2700 (kill-buffer (current-buffer))
2701 (unless errorp (message (concat msg "done") file)))))))
2702
2703
2704 ;; REPLACES ORIGINAL in `bookmark.el'.
2705 ;;
2706 ;; 1. Prefix arg means OVERWRITE.
2707 ;; 2. Use `bmkp-read-bookmark-file-name', not `read-file-name', and use different default.
2708 ;; 3. If OVERWRITE is non-nil:
2709 ;; * Update `bmkp-last-bookmark-file' to `bmkp-current-bookmark-file'.
2710 ;; * Update `bmkp-current-bookmark-file' to FILE .
2711 ;; * If `bmkp-last-as-first-bookmark-file', then update it to FILE and save it to disk.
2712 ;; 4. If the bookmark-file buffer already existed, do not kill it after loading.
2713 ;; 5. Set `bookmarks-already-loaded' regardless of FILE (not just `bookmark-default-file').
2714 ;; 6. Update `bmkp-sorted-alist' (it's a cache).
2715 ;; 7. Final msg says whether overwritten.
2716 ;; 8. Call `bmkp-bmenu-refresh-menu-list' at end.
2717 ;;
2718 ;;;###autoload
2719 (defun bookmark-load (file &optional overwrite batchp) ; Bound to `C-x p l'
2720 "Load bookmarks from FILE (which must be in the standard format).
2721 Without a prefix argument (argument OVERWRITE is nil), add the newly
2722 loaded bookmarks to those already current. They will be saved to the
2723 current bookmark file when bookmarks are saved.
2724
2725 If you do not use a prefix argument, then no existing bookmarks are
2726 overwritten. If you load some bookmarks that have the same names as
2727 bookmarks already defined in your Emacs session, numeric suffixes
2728 \"<2>\", \"<3>\",... are appended as needed to the names of those new
2729 bookmarks to distinguish them.
2730
2731 With a prefix argument, switch the bookmark file currently used,
2732 *replacing* all currently existing bookmarks with the newly loaded
2733 bookmarks. In this case, the value of `bmkp-current-bookmark-file'is
2734 backed up to `bmkp-last-bookmark-file' and then changed to FILE, so
2735 bookmarks will subsequently be saved to FILE. If
2736 `bmkp-last-as-first-bookmark-file' is non-nil then its value is also
2737 changed to FILE and it is saved persistently, so that the next Emacs
2738 session will start with it as the bookmark file. (The value of
2739 `bookmark-default-file' is unaffected.)
2740
2741 Interactively, if any bookmarks have been modified since last saved
2742 then you are asked whether you want to first save them before loading
2743 FILE. If you hit `C-g' then both saving and loading are canceled.
2744
2745 When called from Lisp, non-nil optional arg BATCHP means this is not
2746 an interactive call. In this case, do not interact with the user: do
2747 not ask whether to save the current (unsaved) bookmark list before
2748 loading; do not display any load progress messages; and do not
2749 update/refresh buffer `*Bookmark List*'.
2750
2751 If BATCHP is `save' and bookmarks have been modified since the
2752 bookmark list was last saved, then save the bookmark list before
2753 loading.
2754
2755 If BATCHP is any other non-nil value besides `save', do not save the
2756 bookmark list.
2757
2758 Your initial bookmark file, either `bmkp-last-as-first-bookmark-file'
2759 or `bookmark-default-file', is loaded automatically by Emacs the first
2760 time you use bookmarks in a session - you do not need to load it
2761 manually. Use `bookmark-load' only to load extra bookmarks (with no
2762 prefix arg) or an alternative set of bookmarks (with a prefix arg).
2763
2764 If you use `bookmark-load' to load a file that does not contain a
2765 proper bookmark alist, then when bookmarks are saved the current
2766 bookmark file will likely become corrupted. You should load only
2767 bookmark files that were created using the bookmark functions."
2768 (interactive
2769 (list (let ((default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
2770 (bmkp-default-bookmark-file)
2771 bmkp-last-bookmark-file)))
2772 (bmkp-read-bookmark-file-name
2773 (if current-prefix-arg "Switch to bookmark file: " "Add bookmarks from file: ")
2774 (or (file-name-directory default) "~/")
2775 default
2776 t))
2777 current-prefix-arg))
2778 ;; Maybe save first.
2779 (when (or (eq batchp 'save)
2780 (and (not batchp) (> bookmark-alist-modification-count 0)
2781 (condition-case err
2782 (yes-or-no-p "Save current bookmarks before loading? (`C-g': cancel load) ")
2783 (quit (error "OK, canceled"))
2784 (error (error (error-message-string err))))))
2785 (bookmark-save))
2786 ;; Load.
2787 (setq file (abbreviate-file-name (expand-file-name file)))
2788 (unless (file-readable-p file) (error "Cannot read bookmark file `%s'" file))
2789 (unless batchp (message "Loading bookmarks from `%s'..." file))
2790 (let ((existing-buf (get-file-buffer file)))
2791 (with-current-buffer (let ((enable-local-variables nil)) (find-file-noselect file))
2792 (goto-char (point-min))
2793 (bookmark-maybe-upgrade-file-format)
2794 (let ((blist (bookmark-alist-from-buffer)))
2795 (unless (listp blist) (error "Invalid bookmark list in `%s'" file))
2796 (cond (overwrite
2797 (setq bmkp-last-bookmark-file bmkp-current-bookmark-file
2798 bmkp-current-bookmark-file file
2799 bookmark-alist blist
2800 bookmark-alist-modification-count 0)
2801 (when bmkp-last-as-first-bookmark-file
2802 (customize-save-variable 'bmkp-last-as-first-bookmark-file file)))
2803 (t
2804 (bookmark-import-new-list blist)
2805 (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count))))
2806 (setq bookmarks-already-loaded t ; Systematically, whenever any file is loaded.
2807 bmkp-sorted-alist (bmkp-sort-omit bookmark-alist)))
2808 (unless (eq existing-buf (current-buffer)) (kill-buffer (current-buffer)))))
2809 (unless batchp ; If appropriate, *CALLER* MUST refresh/rebuild, if BATCHP.
2810 (bmkp-refresh/rebuild-menu-list)
2811 (message "%s bookmarks in `%s'" (if overwrite "Switched to" "Added") file)))
2812
2813 ;; REPLACES ORIGINAL in `bookmark.el'.
2814 ;;
2815 ;; 1. Added optional arg MSG-P. Show message if no annotation.
2816 ;; 2. Name buffer after the bookmark.
2817 ;; 3. MSG-P means message if no annotation.
2818 ;; 4. Use `view-mode'. `q' uses `quit-window'.
2819 ;; 5. Fit frame to buffer if `one-windowp'.
2820 ;; 6. Restore frame selection.
2821 ;;
2822 (defun bookmark-show-annotation (bookmark &optional msg-p)
2823 "Display the annotation for BOOKMARK.
2824 BOOKMARK is a bookmark name or a bookmark record.
2825 If it is a record then it need not belong to `bookmark-alist'.
2826 If no annotation and MSG-P is non-nil, show a no-annotation message."
2827 (let* ((bmk (bookmark-get-bookmark bookmark 'NOERROR))
2828 (bmk-name (bmkp-bookmark-name-from-record bmk))
2829 (ann (and bmk (bookmark-get-annotation bmk))))
2830 (if (not (and ann (not (string-equal ann ""))))
2831 (when msg-p (message "Bookmark has no annotation"))
2832 (let ((oframe (selected-frame)))
2833 (save-selected-window
2834 (pop-to-buffer (get-buffer-create (format "*`%s' Annotation*" bmk-name)))
2835 (let ((buffer-read-only nil)) ; Because buffer might already exist, in view mode.
2836 (delete-region (point-min) (point-max))
2837 (insert (concat "Annotation for bookmark '" bmk-name "':\n\n"))
2838 (put-text-property (line-beginning-position -1) (line-end-position 1)
2839 'face 'bmkp-heading)
2840 (insert ann))
2841 (goto-char (point-min))
2842 (view-mode-enter (cons (selected-window) (cons nil 'quit-window)))
2843 (when (fboundp 'fit-frame-if-one-window) (fit-frame-if-one-window)))
2844 (select-frame-set-input-focus oframe)))))
2845
2846
2847 ;; REPLACES ORIGINAL in `bookmark.el'.
2848 ;;
2849 ;; 1. Use name `*Bookmark Annotations*', not `*Bookmark Annotation*'.
2850 ;; 2. Don't list bookmarks that have no annotation.
2851 ;; 3. Highlight bookmark names. Don't indent annotations. Add a blank line after each annotation.
2852 ;; 4. Use `view-mode'. `q' uses `quit-window'.
2853 ;; 5. Fit frame to buffer if `one-windowp'.
2854 ;; 6. Restore frame selection.
2855 ;;
2856 (defun bookmark-show-all-annotations ()
2857 "Display the annotations for all bookmarks."
2858 (let ((oframe (selected-frame)))
2859 (save-selected-window
2860 (pop-to-buffer (get-buffer-create "*Bookmark Annotations*"))
2861 (let ((buffer-read-only nil)) ; Because buffer might already exist, in view mode.
2862 (delete-region (point-min) (point-max))
2863 (dolist (full-record bookmark-alist) ; (Could use `bmkp-annotated-alist-only' here instead.)
2864 (let ((ann (bookmark-get-annotation full-record)))
2865 (when (and ann (not (string-equal ann "")))
2866 (insert (concat (bmkp-bookmark-name-from-record full-record) ":\n"))
2867 (put-text-property (line-beginning-position 0) (line-end-position 0) 'face 'bmkp-heading)
2868 (insert ann) (unless (bolp) (insert "\n\n")))))
2869 (goto-char (point-min))
2870 (view-mode-enter (cons (selected-window) (cons nil 'quit-window)))
2871 (when (fboundp 'fit-frame-if-one-window) (fit-frame-if-one-window))))
2872 (select-frame-set-input-focus oframe)))
2873
2874
2875 ;; REPLACES ORIGINAL in `bookmark.el'.
2876 ;;
2877 ;; Save menu-list state to `bmkp-bmenu-state-file'.
2878 ;;
2879 (defun bookmark-exit-hook-internal () ; This goes on `kill-emacs-hook'.
2880 "Save currently defined bookmarks and perhaps bookmark menu-list state.
2881 Run `bookmark-exit-hook', then save bookmarks if they were updated.
2882 Then save menu-list state to file `bmkp-bmenu-state-file', but only if
2883 that option is non-nil."
2884 (run-hooks 'bookmark-exit-hook)
2885 (when (and bookmark-alist (bookmark-time-to-save-p t)) (bookmark-save))
2886 (bmkp-save-menu-list-state))
2887
2888 ;;(@* "Bookmark+ Functions (`bmkp-*')")
2889 ;;; Bookmark+ Functions (`bmkp-*') -----------------------------------
2890
2891 (defun bmkp-new-bookmark-default-names (&optional first-def)
2892 "Return a list of default names (strings) for a new bookmark.
2893 A non-nil optional arg FIRST-DEF is prepended to the list of names
2894 described below.
2895
2896 If the region is active and non-empty, then the first default name
2897 \(other than FIRST-DEF) is the current buffer name followed by \": \"
2898 and the region prefix (up to `bmkp-bookmark-name-length-max' chars).
2899 The other names are as described below.
2900
2901 Uses option `bmkp-new-bookmark-default-names' to come up with the
2902 other names. To these names, `bookmark-current-bookmark' and
2903 `bookmark-buffer-name' are appened, if available (non-nil).
2904
2905 NOTE: For Emacs versions prior to Emacs 23, return only a single
2906 default name, not a list of names. The name is the first in the list
2907 of names described above for Emacs 23+."
2908 (let ((defs (and first-def (list first-def)))
2909 val)
2910 (unless (and (< emacs-major-version 23) defs) ; Just use FIRST-DEF for Emacs < 23.
2911 ;; If region is active, first default is its text, with buffer name prepended.
2912 (when (and transient-mark-mode mark-active (not (eq (mark) (point))))
2913 (let* ((regname (concat (buffer-name) ": " (buffer-substring (region-beginning) (region-end))))
2914 (defname (bmkp-replace-regexp-in-string
2915 "\n" " "
2916 (progn (save-excursion (goto-char (region-beginning))
2917 (skip-chars-forward " ")
2918 (setq bookmark-yank-point (point)))
2919 (substring regname 0 (min bmkp-bookmark-name-length-max
2920 (length regname)))))))
2921 (if (< emacs-major-version 23)
2922 (setq defs defname)
2923 (add-to-list 'defs defname))))
2924 ;; Names provided by option `bmkp-new-bookmark-default-names',
2925 ;; plus `bookmark-current-bookmark' and `bookmark-buffer-name'.
2926 (unless (and (< emacs-major-version 23) defs)
2927 (catch 'bmkp-new-bookmark-default-names
2928 (dolist (fn bmkp-new-bookmark-default-names)
2929 (when (functionp fn) ; Be sure it is defined and is a function.
2930 (setq val (funcall fn))
2931 (when (and (stringp val) (not (string= "" val)))
2932 (setq val (bmkp-replace-regexp-in-string "\n" " " val))
2933 (if (> emacs-major-version 22)
2934 (add-to-list 'defs val)
2935 (throw 'bmkp-new-bookmark-default-names (setq defs val)))))))
2936 (when (and (< emacs-major-version 23) (null defs))
2937 (setq defs (or bookmark-current-bookmark (bookmark-buffer-name))))
2938 (when (consp defs)
2939 (when bookmark-current-bookmark (push bookmark-current-bookmark defs))
2940 (let ((buf (bookmark-buffer-name))) (when buf (push buf defs)))
2941 (setq defs (nreverse defs)))))
2942 defs))
2943
2944 (defun bmkp-bookmark-record-from-name (bookmark-name &optional noerror memp alist)
2945 "Return the full bookmark (record) that corresponds to BOOKMARK-NAME.
2946 BOOKMARK-NAME must be a string. If it has non-nil text property
2947 `bmkp-full-record' then use that. Otherwise, look for the first
2948 bookmark in ALIST that has the given name.
2949
2950 Non-nil optional arg NOERROR means return nil if BOOKMARK-NAME does
2951 not name a valid bookmark or is valid but is not in ALIST. If NOERROR
2952 is nil then raise an error in this case.
2953
2954 Non-nil optional arg MEMP means that if property `bmkp-full-record' is
2955 available then look up its value (the full bookmark) in ALIST, testing
2956 with `eq'. If that record is not in ALIST, return nil.
2957
2958 Optional arg ALIST defaults to `bookmark-alist'."
2959 (unless alist (setq alist bookmark-alist))
2960 (let ((full (get-text-property 0 'bmkp-full-record bookmark-name)))
2961 (or (and full
2962 (or (not memp) (memq full alist))
2963 full)
2964 ;; Punt: return first matching bookmark in ALIST.
2965 (if (fboundp 'assoc-string) ; Emacs 22+. Use `assoc-string' for its CASE-FOLD arg.
2966 (assoc-string bookmark-name alist bookmark-completion-ignore-case)
2967 (assoc bookmark-name alist))
2968 (and (not noerror) (error "No such bookmark in bookmark list: `%s'" bookmark-name)))))
2969
2970 (defun bmkp-rename-for-marked-and-omitted-lists (old new)
2971 "Replace OLD bookmark name with NEW in marked and omitted lists."
2972 (when (bmkp-marked-bookmark-p old)
2973 (setq bmkp-bmenu-marked-bookmarks (bmkp-delete-bookmark-name-from-list old
2974 bmkp-bmenu-marked-bookmarks))
2975 (push new bmkp-bmenu-marked-bookmarks))
2976 (when (bmkp-omitted-bookmark-p old)
2977 (setq bmkp-bmenu-omitted-bookmarks (bmkp-delete-bookmark-name-from-list old
2978 bmkp-bmenu-omitted-bookmarks))
2979 (push new bmkp-bmenu-omitted-bookmarks)))
2980
2981 (defun bmkp-get-bookmark-in-alist (bookmark &optional noerror alist)
2982 "Return the full bookmark in ALIST that corresponds to BOOKMARK.
2983 BOOKMARK is a bookmark name or a bookmark record.
2984
2985 Non-nil optional arg NOERROR means return nil if BOOKMARK does not
2986 represent a valid bookmark or is valid but is not in ALIST. If
2987 NOERROR is nil then raise an error in this case.
2988
2989 Optional arg ALIST defaults to `bookmark-alist'.
2990
2991 Bookmark membership in ALIST is tested using `eq'.
2992
2993 If BOOKMARK is a bookmark name instead of a full bookmark then return
2994 what `bmkp-bookmark-record-from-name' with non-nil arg MEMP returns.
2995
2996 This function is like `bookmark-get-bookmark', except that
2997 `bookmark-get-bookmark' tests whether BOOKMARK is in `bookmark-alist'
2998 only when it is a string (a bookmark name, not a full bookmark). When
2999 BOOKMARK is a full bookmark `bookmark-get-bookmark' is thus not a test
3000 for its existence, as is `bmkp-get-bookmark-in-alist'."
3001 (cond ((consp bookmark) (and (memq bookmark bookmark-alist) bookmark))
3002 ((stringp bookmark) (bmkp-bookmark-record-from-name bookmark noerror 'MEMP))
3003 (t (and (not noerror) (error "Invalid bookmark: `%s'" bookmark)))))
3004
3005 (defun bmkp-default-bookmark-file ()
3006 "`bmkp-last-as-first-bookmark-file', or `bookmark-default-file' if nil."
3007 (or bmkp-last-as-first-bookmark-file bookmark-default-file))
3008
3009 (defun bmkp-completing-read-lax (prompt &optional default alist pred hist)
3010 "Read a bookmark name, prompting with PROMPT.
3011 Like `bookmark-completing-read', but completion is lax: your input
3012 need not match any existing bookmark name.
3013
3014 In addition:
3015 * You can use `SPC' and `?' freely when typing the name.
3016 * You can use `C-M-w' repeatedly to yank consecutive words from the
3017 current buffer (see `bookmark-yank-word')."
3018 (let ((orig-C-M-w (lookup-key minibuffer-local-completion-map (kbd "C-M-w")))
3019 (orig-C-M-u (lookup-key minibuffer-local-completion-map (kbd "C-M-u")))
3020 (orig-SPC (lookup-key minibuffer-local-completion-map (kbd "SPC")))
3021 (orig-qmark (lookup-key minibuffer-local-completion-map (kbd "?"))))
3022 (unwind-protect
3023 (progn (define-key minibuffer-local-completion-map (kbd "C-M-w") 'bookmark-yank-word)
3024 (define-key minibuffer-local-completion-map (kbd "C-M-u") 'bookmark-insert-current-bookmark)
3025 (unless (and (boundp 'icicle-mode) icicle-mode
3026 (eq orig-SPC 'icicle-self-insert))
3027 (define-key minibuffer-local-completion-map (kbd "SPC") 'self-insert-command))
3028 (unless (and (boundp 'icicle-mode) icicle-mode
3029 (eq orig-qmark 'icicle-self-insert))
3030 (define-key minibuffer-local-completion-map (kbd "?") 'self-insert-command))
3031 (bmkp-completing-read-1 prompt default alist pred hist t))
3032 (define-key minibuffer-local-completion-map (kbd "C-M-w") orig-C-M-w)
3033 (define-key minibuffer-local-completion-map (kbd "C-M-u") orig-C-M-u)
3034 (define-key minibuffer-local-completion-map (kbd "SPC") orig-SPC)
3035 (define-key minibuffer-local-completion-map (kbd "?") orig-qmark))))
3036
3037 (defun bmkp-completing-read-1 (prompt default alist pred hist laxp)
3038 "Helper for `bookmark-completing-read(-lax)'.
3039 LAXP non-nil means use lax completion."
3040 (bookmark-maybe-load-default-file)
3041 (setq alist (or alist bookmark-alist))
3042 (if (and (not laxp)
3043 (listp last-nonmenu-event)
3044 (or (eq t bmkp-menu-popup-max-length)
3045 (and (integerp bmkp-menu-popup-max-length)
3046 (< (length alist) bmkp-menu-popup-max-length))))
3047 (bookmark-menu-popup-paned-menu
3048 t prompt
3049 (if bmkp-sort-comparer ; Test whether to sort, but always use `string-lessp'.
3050 (sort (bookmark-all-names alist) 'string-lessp)
3051 (bookmark-all-names alist)))
3052 (let* ((icicle-delete-candidate-object (lambda (cand) ; For `S-delete' in Icicles.
3053 (bookmark-delete
3054 (icicle-transform-multi-completion cand))))
3055 (completion-ignore-case bookmark-completion-ignore-case)
3056 (default default)
3057 (prompt (if default
3058 (concat prompt
3059 (format " (%s): "
3060 (if (consp default) (car default) default)
3061 default))
3062 (concat prompt ": ")))
3063 (str (completing-read prompt alist pred (not laxp) nil
3064 (or hist 'bookmark-history) default)))
3065 (when (consp default) (setq default (car default))) ; Emacs 23+
3066 (if (and (string-equal "" str) default) default str))))
3067
3068 (defun bmkp-jump-1 (bookmark display-function use-region-p)
3069 "Helper function for `bookmark-jump' commands.
3070 BOOKMARK is a bookmark name or a bookmark record.
3071 DISPLAY-FUNCTION is passed to `bookmark--jump-via'.
3072 Non-nil USE-REGION-P means activate the region, if recorded."
3073 (setq bookmark (bookmark-get-bookmark bookmark 'NOERROR))
3074 (unless bookmark (error "No bookmark specified"))
3075 (bookmark-maybe-historicize-string (bmkp-bookmark-name-from-record bookmark))
3076 (let ((bmkp-use-region (if use-region-p (not bmkp-use-region) bmkp-use-region)))
3077 (bookmark--jump-via bookmark display-function)))
3078
3079 (defun bmkp-select-buffer-other-window (buffer)
3080 "Select BUFFER in another window.
3081 If `bmkp-other-window-pop-to-flag' is non-nil, then use
3082 `pop-to-buffer'. Otherwise, use `switch-to-buffer-other-window'."
3083 (if bmkp-other-window-pop-to-flag
3084 (pop-to-buffer buffer t)
3085 (switch-to-buffer-other-window buffer)))
3086
3087 (defun bmkp-maybe-save-bookmarks (&optional same-count-p)
3088 "Increment save counter and maybe save `bookmark-alist'.
3089 Non-nil optional arg SAME-COUNT-P means do not increment
3090 `bookmark-alist-modification-count'."
3091 (unless same-count-p (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count)))
3092 (when (bookmark-time-to-save-p) (bookmark-save)))
3093
3094 ;;;###autoload
3095 (defun bmkp-edit-bookmark-name-and-file (bookmark &optional edit-record-p)
3096 ; Bound to `C-x p r' (`r' in bookmark list)
3097 "Edit BOOKMARK's name and file name, and maybe save them.
3098 Return a list of the new bookmark name and new file name.
3099 BOOKMARK is a bookmark name or a bookmark record.
3100
3101 Without a prefix arg, you are prompted for the new bookmark name and
3102 the new file name. When entering the new name you can use completion
3103 against existing names. This completion is lax, so you can easily
3104 edit an existing name. See `bookmark-set' for particular keys
3105 available during this input.
3106
3107 With a prefix arg, edit the complete bookmark record (the
3108 internal, Lisp form)."
3109 (interactive
3110 (list (bookmark-completing-read
3111 (concat "Edit " (and current-prefix-arg "internal record for ") "bookmark")
3112 (bmkp-default-bookmark-name))
3113 current-prefix-arg))
3114 (setq bookmark (bmkp-get-bookmark-in-alist bookmark))
3115 (if edit-record-p
3116 (bmkp-edit-bookmark-record bookmark)
3117 (let* ((bookmark-name (bmkp-bookmark-name-from-record bookmark))
3118 (bookmark-filename (bookmark-get-filename bookmark-name))
3119 (new-bmk-name (bmkp-completing-read-lax
3120 "New bookmark name: " bookmark-name))
3121 (icicle-unpropertize-completion-result-flag t) ; For `read-file-name'.
3122 (new-filename (read-file-name
3123 "New file name (location): "
3124 (and bookmark-filename
3125 (file-name-directory bookmark-filename))
3126 bookmark-filename))
3127 (changed-bmk-name-p (and (not (equal new-bmk-name ""))
3128 (not (equal new-bmk-name bookmark-name))))
3129 (changed-filename-p (and (not (equal new-filename ""))
3130 (not (equal new-filename bookmark-filename)))))
3131
3132
3133 (when (or changed-bmk-name-p changed-filename-p)
3134 (when changed-bmk-name-p (bookmark-rename bookmark-name new-bmk-name 'BATCHP))
3135 (when changed-filename-p (bookmark-set-filename new-bmk-name new-filename))
3136 ;; Change location for Dired too, but not if different from original file name (e.g. a cons).
3137 (let ((dired-dir (bookmark-prop-get new-bmk-name 'dired-directory)))
3138 (when (and dired-dir (equal dired-dir bookmark-filename))
3139 (bookmark-prop-set new-bmk-name 'dired-directory new-filename)))
3140 (bmkp-maybe-save-bookmarks) ; Maybe save automatically.
3141 (when (and bookmark-alist-modification-count ; Did not save automatically. Ask user.
3142 (y-or-n-p "Save changes? "))
3143 (bookmark-save))
3144 (list new-bmk-name new-filename)))))
3145
3146 (define-derived-mode bmkp-edit-bookmark-records-mode emacs-lisp-mode
3147 "Edit Bookmark Records"
3148 "Mode for editing a list of bookmark records, as in `bookmark-alist'.
3149 When you have finished editing, use `\\[bmkp-edit-bookmark-record-send]'."
3150 :group 'bookmark-plus)
3151
3152 ;; This binding must be defined *after* the mode, so `bmkp-edit-bookmark-records-mode-map' is defined.
3153 ;; (Alternatively, we could use a `defvar' to define `bmkp-edit-bookmark-records-mode-map' before
3154 ;; calling `define-derived-mode'.)
3155 (define-key bmkp-edit-bookmark-records-mode-map "\C-c\C-c" 'bmkp-edit-bookmark-records-send)
3156
3157 (defvar bmkp-edit-bookmark-records-number 0
3158 "NUmber of bookmard records being edited.")
3159
3160 ;;;###autoload
3161 (defun bmkp-edit-bookmark-records-send (&optional msg-p) ; Bound to `C-c C-c' in records-editing buffer.
3162 "Update `bookmark-alist' with buffer contents: a bookmark alist.
3163 Lines beginning with `;;' are ignored.
3164 Non-interactively, optional arg MSG-P means display progress messages.
3165
3166 This assumes that the bookmarks in the buffer are the marked bookmarks
3167 in `*Bookmark List*'. That is, it assumes that the buffer was created
3168 by `bmkp-bmenu-edit-marked' (`\\<bookmark-bmenu-mode-map>\\[bmkp-bmenu-edit-marked]' in `*Bookmark List*')."
3169 (interactive "p")
3170 (unless (eq major-mode 'bmkp-edit-bookmark-records-mode)
3171 (error "Not in `bmkp-edit-bookmark-records-mode'"))
3172 (when msg-p (message "Reading edited bookmarks..."))
3173 (let ((editbuf (current-buffer))
3174 (read-error-msg
3175 (catch 'bmkp-edit-bookmark-records-send
3176 (let ((edited-bookmarks (condition-case err
3177 (save-excursion (goto-char (point-min)) (read (current-buffer)))
3178 (error (throw 'bmkp-edit-bookmark-records-send
3179 (error-message-string err)))))
3180 (orig-bmks (bmkp-marked-bookmarks-only))
3181 (bookmark-save-flag (and (not bmkp-count-multi-mods-as-one-flag)
3182 bookmark-save-flag))) ; Save only after `dolist'.
3183 (cond ((not (listp edited-bookmarks))
3184 (throw 'bmkp-edit-bookmark-records-send "Not a list of bookmarks"))
3185 ((not (= (length edited-bookmarks) bmkp-edit-bookmark-records-number))
3186 (throw 'bmkp-edit-bookmark-records-send
3187 (format "Need %d bookmarks, but there seem to be %d"
3188 bmkp-edit-bookmark-records-number (length edited-bookmarks)))))
3189 (dolist (edited-bmk edited-bookmarks)
3190 (unless (and (consp edited-bmk) (stringp (car edited-bmk))) ; Sanity check.
3191 (throw 'bmkp-edit-bookmark-records-send (format "Invalid bookmark: `%s'" edited-bmk)))
3192 (let ((bname (bmkp-bookmark-name-from-record edited-bmk))
3193 (data (bmkp-bookmark-data-from-record edited-bmk)))
3194 ;; Put the full bookmark on its name as property `bmkp-full-record'.
3195 ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
3196 ;; If it needs to be stripped, that will be done when saving.
3197 (put-text-property 0 (length bname) 'bmkp-full-record edited-bmk bname)
3198 ;; Update the original bookmark (same cons cell) with what's in the edited version.
3199 (setcar (car orig-bmks) bname)
3200 (setcdr (car orig-bmks) data)
3201 ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
3202 (unless (memq (car orig-bmks) bmkp-modified-bookmarks)
3203 (setq bmkp-modified-bookmarks (cons (car orig-bmks) bmkp-modified-bookmarks)))
3204 (setq orig-bmks (cdr orig-bmks))))
3205 ;; Update using modified ORIG-BMKS.
3206 (setq bmkp-bmenu-marked-bookmarks (mapcar #'bmkp-bookmark-name-from-record
3207 bmkp-modified-bookmarks)
3208 bmkp-sorted-alist (bmkp-sort-omit bookmark-alist)
3209 bookmark-alist-modification-count (1+ bookmark-alist-modification-count)))
3210 nil)))
3211 (if (stringp read-error-msg)
3212 (if msg-p (message "%s --> edit and try again" read-error-msg) (error read-error-msg))
3213 (when (get-buffer editbuf) (kill-buffer editbuf))
3214 (bmkp-refresh/rebuild-menu-list nil (not msg-p)))))
3215
3216 (define-derived-mode bmkp-edit-bookmark-record-mode emacs-lisp-mode
3217 "Edit Bookmark Record"
3218 "Mode for editing an internal bookmark record.
3219 When you have finished editing, use `\\[bmkp-edit-bookmark-record-send]'."
3220 :group 'bookmark-plus)
3221
3222 ;; This binding must be defined *after* the mode, so `bmkp-edit-bookmark-record-mode-map' is defined.
3223 ;; (Alternatively, we could use a `defvar' to define `bmkp-edit-bookmark-record-mode-map' before
3224 ;; calling `define-derived-mode'.)
3225 (define-key bmkp-edit-bookmark-record-mode-map "\C-c\C-c" 'bmkp-edit-bookmark-record-send)
3226
3227 ;;;###autoload
3228 (defun bmkp-edit-bookmark-record (bookmark) ; Bound to `C-x p e'.
3229 "Edit the full record (the Lisp sexp) for BOOKMARK.
3230 BOOKMARK is a bookmark name or a bookmark record.
3231 When you finish editing, use `\\[bmkp-edit-bookmark-record-send]'.
3232 The current bookmark list is then updated to reflect your edits."
3233 (interactive (list (bookmark-completing-read "Edit Lisp record for bookmark:"
3234 (bmkp-default-bookmark-name))))
3235 (bookmark-maybe-load-default-file)
3236 (setq bmkp-edit-bookmark-orig-record (bmkp-get-bookmark-in-alist bookmark))
3237 (let* ((bmk-copy (copy-sequence bmkp-edit-bookmark-orig-record)) ; Shallow copy
3238 (bname (bmkp-bookmark-name-from-record bmk-copy))
3239 (bufname (format "*Edit Record for Bookmark `%s'*" bname)))
3240 (set-text-properties 0 (length bname) nil bname) ; Strip properties from (copied) name string.
3241 (bookmark-maybe-historicize-string bname)
3242 (bmkp-with-output-to-plain-temp-buffer bufname
3243 (princ
3244 (substitute-command-keys
3245 (concat ";; Edit the Lisp record for bookmark\n;;\n"
3246 ";; `" bname "'\n;;\n"
3247 ";; Type \\<bmkp-edit-bookmark-record-mode-map>\
3248 `\\[bmkp-edit-bookmark-record-send]' when done.\n;;\n")))
3249 ;; (let ((print-circle t)) (pp bmk)) ; $$$$$$ Binding should not really be needed now.
3250 (pp bmk-copy)
3251 (goto-char (point-min)))
3252 (pop-to-buffer bufname)
3253 (buffer-enable-undo)
3254 (with-current-buffer (get-buffer bufname) (bmkp-edit-bookmark-record-mode))))
3255
3256 ;;;###autoload
3257 (defun bmkp-edit-bookmark-record-send (&optional msg-p) ; Bound to `C-c C-c' in record-editing buffer.
3258 "Update `bookmark-alist' with buffer contents: a bookmark record.
3259 Lines beginning with `;;' are ignored.
3260 Non-interactively, optional arg MSG-P means display progress messages."
3261 (interactive "p")
3262 (unless (eq major-mode 'bmkp-edit-bookmark-record-mode)
3263 (error "Not in `bmkp-edit-bookmark-record-mode'"))
3264 (when msg-p (message "Reading edited bookmark..."))
3265 (let* ((editbuf (current-buffer))
3266 (bmk-name nil)
3267 (read-error-msg
3268 (catch 'bmkp-edit-bookmark-record-send
3269 (let ((edited-bmk
3270 (condition-case err
3271 (save-excursion (goto-char (point-min)) (read (current-buffer)))
3272 (error (throw 'bmkp-edit-bookmark-record-send (error-message-string err))))))
3273 (unless (and (consp edited-bmk) (stringp (car edited-bmk)))
3274 (throw 'bmkp-edit-bookmark-record-send (format "Invalid bookmark: `%s'" edited-bmk)))
3275 (let ((bname (bmkp-bookmark-name-from-record edited-bmk))
3276 (data (bmkp-bookmark-data-from-record edited-bmk)))
3277 ;; Put the full bookmark on its name as property `bmkp-full-record'.
3278 ;; Do this regardless of Emacs version and `bmkp-propertize-bookmark-names-flag'.
3279 ;; If it needs to be stripped, that will be done when saving.
3280 (put-text-property 0 (length bname) 'bmkp-full-record edited-bmk bname)
3281 ;; Update the original bookmark with what's in the edited version.
3282 (setcar bmkp-edit-bookmark-orig-record bname)
3283 (setcdr bmkp-edit-bookmark-orig-record data)
3284 ;; This is the same as `add-to-list' with `EQ' (not available for Emacs 20-21).
3285 (unless (memq bmkp-edit-bookmark-orig-record bmkp-modified-bookmarks)
3286 (setq bmkp-modified-bookmarks (cons bmkp-edit-bookmark-orig-record
3287 bmkp-modified-bookmarks)))
3288 (setq bmk-name bname)) ; Save for bookmark-list display, below.
3289 (setq bmkp-sorted-alist (bmkp-sort-omit bookmark-alist)
3290 bookmark-alist-modification-count (1+ bookmark-alist-modification-count)))
3291 nil)))
3292 (if (stringp read-error-msg)
3293 (if msg-p
3294 (message "%s --> edit and try again" read-error-msg)
3295 (error read-error-msg))
3296 (when (get-buffer editbuf) (kill-buffer editbuf))
3297 (bmkp-refresh/rebuild-menu-list bmk-name (not msg-p))))
3298 (setq bmkp-edit-bookmark-orig-record nil)) ; Reset it.
3299
3300 (define-derived-mode bmkp-edit-tags-mode emacs-lisp-mode
3301 "Edit Bookmark Tags"
3302 "Mode for editing bookmark tags.
3303 When you have finished composing, type \\[bmkp-edit-tags-send]."
3304 :group 'bookmark-plus)
3305
3306 ;; This binding must be defined *after* the mode, so `bmkp-edit-tags-mode-map' is defined.
3307 ;; (Alternatively, we could use a `defvar' to define `bmkp-edit-tags-mode-map' before
3308 ;; calling `define-derived-mode'.)
3309 (define-key bmkp-edit-tags-mode-map "\C-c\C-c" 'bmkp-edit-tags-send)
3310
3311 ;;;###autoload
3312 (defun bmkp-edit-tags (bookmark) ; Bound to `C-x p t e'
3313 "Edit BOOKMARK's tags, and maybe save the result.
3314 The edited value must be a list each of whose elements is either a
3315 string or a cons whose key is a string.
3316 BOOKMARK is a bookmark name or a bookmark record."
3317 (interactive (list (bookmark-completing-read "Edit tags for bookmark" (bmkp-default-bookmark-name))))
3318 (setq bookmark (bmkp-get-bookmark-in-alist bookmark))
3319 (let* ((btags (bmkp-get-tags bookmark))
3320 (bmkname (bmkp-bookmark-name-from-record bookmark))
3321 (edbuf (format "*Edit Tags for Bookmark `%s'*" bmkname)))
3322 (setq bmkp-return-buffer (current-buffer))
3323 (bmkp-with-output-to-plain-temp-buffer edbuf
3324 (princ
3325 (substitute-command-keys
3326 (concat ";; Edit tags for bookmark\n;;\n;; \"" bmkname "\"\n;;\n"
3327 ";; The edited value must be a list each of whose elements is\n"
3328 ";; either a string or a cons whose key is a string.\n;;\n"
3329 ";; DO NOT MODIFY THESE COMMENTS.\n;;\n"
3330 ";; Type \\<bmkp-edit-tags-mode-map>`\\[bmkp-edit-tags-send]' when done.\n\n")))
3331 (let ((print-circle t)) (pp btags))
3332 (goto-char (point-min)))
3333 (pop-to-buffer edbuf)
3334 (buffer-enable-undo)
3335 (with-current-buffer (get-buffer edbuf) (bmkp-edit-tags-mode))))
3336
3337 ;;;###autoload
3338 (defun bmkp-edit-tags-send (&optional batchp)
3339 "Use buffer contents as the internal form of a bookmark's tags.
3340 DO NOT MODIFY the header comment lines, which begin with `;;'."
3341 (interactive)
3342 (unless (eq major-mode 'bmkp-edit-tags-mode) (error "Not in `bmkp-edit-tags-mode'"))
3343 (let (bname)
3344 (unwind-protect
3345 (let (tags bmk)
3346 (goto-char (point-min))
3347 (unless (search-forward ";; Edit tags for bookmark\n;;\n;; ")
3348 (error "Missing header in edit buffer"))
3349 (unless (stringp (setq bname (read (current-buffer))))
3350 (error "Bad bookmark name in edit-buffer header"))
3351 (unless (setq bmk (bmkp-get-bookmark-in-alist bname 'NOERROR))
3352 (error "No such bookmark: `%s'" bname))
3353 (unless (bmkp-bookmark-type bmk) (error "Invalid bookmark"))
3354 (goto-char (point-min))
3355 (setq tags (read (current-buffer)))
3356 (unless (listp tags) (error "Tags sexp is not a list of strings or an alist with string keys"))
3357 (bookmark-prop-set bmk 'tags tags)
3358 (setq bname (bmkp-bookmark-name-from-record bmk))
3359 (bmkp-record-visit bmk batchp)
3360 (bmkp-refresh/rebuild-menu-list bname batchp)
3361 (bmkp-maybe-save-bookmarks)
3362 (unless batchp (message "Updated bookmark file with edited tags")))
3363 (kill-buffer (current-buffer)))
3364 (when bmkp-return-buffer
3365 (pop-to-buffer bmkp-return-buffer)
3366 (when (equal (buffer-name (current-buffer)) "*Bookmark List*")
3367 (bmkp-bmenu-goto-bookmark-named bname)))))
3368
3369 (defun bmkp-bookmark-type (bookmark)
3370 "Return the type of BOOKMARK or nil if no type is recognized.
3371 Return nil if the bookmark record is not recognized (invalid).
3372 See the code for the possible non-nil return values.
3373 BOOKMARK is a bookmark name or a bookmark record.
3374 If it is a record then it need not belong to `bookmark-alist'."
3375 (condition-case nil
3376 (progn
3377 ;; If BOOKMARK is already a bookmark record, not a bookmark name, then we must use it.
3378 ;; If we used the name instead, then tests such as `bookmark-get-filename' would fail,
3379 ;; because they call `bookmark-get-bookmark', which, for a string, checks whether the
3380 ;; bookmark exists in `bookmark-alist'. But we want to be able to use `bmkp-bookmark-type'
3381 ;; to get the type of any bookmark record, not necessarily one that is in `bookmark-alist'.
3382 (when (stringp bookmark) (setq bookmark (bookmark-get-bookmark bookmark)))
3383 (let ((filep (bookmark-get-filename bookmark)))
3384 (cond ((bmkp-sequence-bookmark-p bookmark) 'bmkp-sequence-bookmark-p)
3385 ((bmkp-function-bookmark-p bookmark) 'bmkp-function-bookmark-p)
3386 ((bmkp-variable-list-bookmark-p bookmark) 'bmkp-variable-list-bookmark-p)
3387 ((bmkp-url-bookmark-p bookmark) 'bmkp-url-bookmark-p)
3388 ((bmkp-gnus-bookmark-p bookmark) 'bmkp-gnus-bookmark-p)
3389 ((bmkp-desktop-bookmark-p bookmark) 'bmkp-desktop-bookmark-p)
3390 ((bmkp-bookmark-file-bookmark-p bookmark) 'bmkp-bookmark-file-bookmark-p)
3391 ((bmkp-bookmark-list-bookmark-p bookmark) 'bmkp-bookmark-list-bookmark-p)
3392 ((bmkp-man-bookmark-p bookmark) 'bmkp-man-bookmark-p)
3393 ((bmkp-info-bookmark-p bookmark) 'bmkp-info-bookmark-p)
3394 ((bookmark-get-handler bookmark) 'bookmark-get-handler)
3395 ((bmkp-region-bookmark-p bookmark) 'bmkp-region-bookmark-p)
3396 ;; Make sure we test for remoteness before any other tests of the file itself
3397 ;; (e.g. `file-exists-p'). We do not want to prompt for a password etc.
3398 ((and filep (bmkp-file-remote-p filep)) 'remote-file)
3399 ((and filep (file-directory-p filep)) 'local-directory)
3400 (filep 'local-file)
3401 ((and (bmkp-get-buffer-name bookmark)
3402 (or (not filep)
3403 (equal filep bmkp-non-file-filename))) 'buffer)
3404 (t nil))))
3405 (error nil)))
3406
3407 (defun bmkp-record-visit (bookmark &optional batchp)
3408 "Update the data recording a visit to BOOKMARK.
3409 BOOKMARK is a bookmark name or a bookmark record.
3410 This increments the `visits' entry and sets the `time' entry to the
3411 current time. If either an entry is not present, it is added (with 0
3412 value for `visits').
3413 With non-nil optional arg BATCHP, do not rebuild the menu list.
3414
3415 Although this function modifies BOOKMARK, it does not increment
3416 `bookmark-alist-modification-count', and it does not add BOOKMARK to
3417 `bmkp-modified-bookmarks'. This is so that simply recording the visit
3418 does not count toward needing to save or showing BOOKMARK as modified."
3419 (let ((vis (bookmark-prop-get bookmark 'visits))
3420 (bmkp-modified-bookmarks bmkp-modified-bookmarks))
3421 (if vis (bookmark-prop-set bookmark 'visits (1+ vis)) (bookmark-prop-set bookmark 'visits 0))
3422 (bookmark-prop-set bookmark 'time (current-time))
3423 (unless batchp (bookmark-bmenu-surreptitiously-rebuild-list 'NO-MSG-P))
3424 (let ((bookmark-save-flag nil)) (bmkp-maybe-save-bookmarks 'SAME-COUNT-P))))
3425
3426 (defun bmkp-default-bookmark-name (&optional alist)
3427 "Default bookmark name. See option `bmkp-default-bookmark-name'.
3428 Non-nil ALIST means return nil unless the default names a bookmark in
3429 ALIST."
3430 (let ((bname (if (equal (buffer-name (current-buffer)) "*Bookmark List*")
3431 (bookmark-bmenu-bookmark)
3432 (if (fboundp 'bmkp-default-lighted)
3433 (if (eq 'highlighted bmkp-default-bookmark-name)
3434 (or (bmkp-default-lighted) bookmark-current-bookmark)
3435 (or bookmark-current-bookmark (bmkp-default-lighted)))
3436 bookmark-current-bookmark))))
3437 (when (and bname alist)
3438 (setq bname (bmkp-bookmark-name-from-record (bmkp-bookmark-record-from-name
3439 bname 'NOERROR 'MEMP alist))))
3440 bname))
3441
3442 (defun bmkp-buffer-names ()
3443 "Buffer names used by existing bookmarks that really have buffers.
3444 This excludes buffers for bookmarks such as desktops that are not
3445 really associated with a buffer."
3446 (let ((bufs ())
3447 buf)
3448 (dolist (bmk bookmark-alist)
3449 (when (and (not (bmkp-desktop-bookmark-p bmk))
3450 (not (bmkp-bookmark-file-bookmark-p bmk))
3451 (not (bmkp-sequence-bookmark-p bmk))
3452 (not (bmkp-function-bookmark-p bmk))
3453 (not (bmkp-variable-list-bookmark-p bmk))
3454 (setq buf (bmkp-get-buffer-name bmk)))
3455 (add-to-list 'bufs buf)))
3456 bufs))
3457
3458 (defun bmkp-file-names ()
3459 "The absolute file names used by the existing bookmarks.
3460 This excludes the pseudo file name `bmkp-non-file-filename'."
3461 (let ((files ())
3462 file)
3463 (dolist (bmk bookmark-alist)
3464 (when (and (setq file (bookmark-get-filename bmk)) (not (equal file bmkp-non-file-filename)))
3465 (add-to-list 'files file)))
3466 files))
3467
3468 ;;;###autoload
3469 (defun bmkp-send-bug-report () ; Not bound
3470 "Send a bug report about a Bookmark+ problem."
3471 (interactive)
3472 (browse-url (format (concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
3473 Bookmark+ bug: \
3474 &body=Describe bug below, using a precise recipe that starts with `emacs -Q' or `emacs -q'. \
3475 Be sure to mention the `Update #' from header of the particular Bookmark+ file header.\
3476 %%0A%%0AEmacs version: %s")
3477 (emacs-version))))
3478
3479 ;;;###autoload
3480 (defun bmkp-toggle-bookmark-set-refreshes () ; Not bound
3481 "Toggle `bookmark-set' refreshing `bmkp-latest-bookmark-alist'.
3482 Add/remove `bmkp-refresh-latest-bookmark-list' to/from
3483 `bmkp-after-set-hook'."
3484 (interactive)
3485 (if (member 'bmkp-refresh-latest-bookmark-list bmkp-after-set-hook)
3486 (remove-hook 'bmkp-after-set-hook 'bmkp-refresh-latest-bookmark-list)
3487 (add-hook 'bmkp-after-set-hook 'bmkp-refresh-latest-bookmark-list)))
3488
3489 (defun bmkp-refresh-latest-bookmark-list ()
3490 "Refresh `bmkp-latest-bookmark-alist' to reflect `bookmark-alist'."
3491 (setq bmkp-latest-bookmark-alist (if bmkp-bmenu-filter-function
3492 (funcall bmkp-bmenu-filter-function)
3493 bookmark-alist)))
3494
3495 ;;;###autoload
3496 (defun bmkp-toggle-saving-menu-list-state () ; Bound to `C-M-~' in bookmark list
3497 "Toggle the value of option `bmkp-bmenu-state-file'.
3498 Tip: You can use this before quitting Emacs, to not save the state.
3499 If the initial value of `bmkp-bmenu-state-file' is nil, then this
3500 command has no effect."
3501 (interactive)
3502 (unless (or bmkp-last-bmenu-state-file bmkp-bmenu-state-file)
3503 (error "Cannot toggle: initial value of `bmkp-bmenu-state-file' is nil"))
3504 (setq bmkp-last-bmenu-state-file (prog1 bmkp-bmenu-state-file
3505 (setq bmkp-bmenu-state-file bmkp-last-bmenu-state-file)))
3506 (message (if bmkp-bmenu-state-file
3507 "Autosaving of bookmark list state is now ON"
3508 "Autosaving of bookmark list state is now OFF")))
3509
3510 ;;;###autoload
3511 (defun bmkp-save-menu-list-state (&optional msg-p) ; Used in `bookmark-exit-hook-internal'.
3512 "Save menu-list state, unless not saving or list has not yet been shown.
3513 The state is saved to the value of `bmkp-bmenu-state-file'.
3514 Non-interactively, optional arg MSG-P means display progress messages."
3515 (interactive "p")
3516 (when (and (not bmkp-bmenu-first-time-p) bmkp-bmenu-state-file)
3517 (when msg-p (message "Saving bookmark-list display state..."))
3518 (let ((config-list
3519 `((last-sort-comparer . ,bmkp-sort-comparer)
3520 (last-reverse-sort-p . ,bmkp-reverse-sort-p)
3521 (last-reverse-multi-sort-p . ,bmkp-reverse-multi-sort-p)
3522 (last-latest-bookmark-alist . ,(bmkp-maybe-unpropertize-bookmark-names
3523 bmkp-latest-bookmark-alist))
3524 (last-bmenu-omitted-bookmarks . ,(bmkp-maybe-unpropertize-bookmark-names
3525 bmkp-bmenu-omitted-bookmarks))
3526 (last-bmenu-marked-bookmarks . ,(bmkp-maybe-unpropertize-bookmark-names
3527 bmkp-bmenu-marked-bookmarks))
3528 (last-bmenu-filter-function . ,bmkp-bmenu-filter-function)
3529 (last-bmenu-filter-pattern . ,bmkp-bmenu-filter-pattern)
3530 (last-bmenu-title . ,bmkp-bmenu-title)
3531 (last-bmenu-bookmark . ,(and (get-buffer "*Bookmark List*")
3532 (with-current-buffer
3533 (get-buffer "*Bookmark List*")
3534 (bookmark-bmenu-bookmark))))
3535 (last-specific-buffer . ,bmkp-last-specific-buffer)
3536 (last-specific-file . ,bmkp-last-specific-file)
3537 (last-bmenu-toggle-filenames . ,bookmark-bmenu-toggle-filenames)
3538 (last-bmenu-before-hide-marked-alist . ,(bmkp-maybe-unpropertize-bookmark-names
3539 bmkp-bmenu-before-hide-marked-alist))
3540 (last-bmenu-before-hide-unmarked-alist . ,(bmkp-maybe-unpropertize-bookmark-names
3541 bmkp-bmenu-before-hide-unmarked-alist))
3542 (last-bookmark-file . ,(convert-standard-filename
3543 (expand-file-name
3544 bmkp-current-bookmark-file))))))
3545 (with-current-buffer (get-buffer-create " *Menu-List State*")
3546 (goto-char (point-min))
3547 (delete-region (point-min) (point-max))
3548 (let ((print-length nil)
3549 (print-level nil)
3550 (print-circle t))
3551 (pp config-list (current-buffer)))
3552 (condition-case nil
3553 (write-region (point-min) (point-max) bmkp-bmenu-state-file)
3554 (file-error (message "Cannot write `%s'" bmkp-bmenu-state-file)))
3555 (kill-buffer (current-buffer)))
3556 (when msg-p (message "Saving bookmark-list display state...done")))))
3557
3558 ;;;###autoload
3559 (defun bmkp-toggle-saving-bookmark-file (&optional msg-p) ; Bound to `M-~' in bookmark list
3560 "Toggle the value of option `bookmark-save-flag'.
3561 If the initial value of `bookmark-save-flag' is nil, then this
3562 command has no effect.
3563 Non-interactively, non-nil MSG-P means display a status message."
3564 (interactive "p")
3565 (unless (or bmkp-last-save-flag-value bookmark-save-flag)
3566 (error "Cannot toggle: initial value of `bookmark-save-flag' is nil"))
3567 (setq bmkp-last-save-flag-value (prog1 bookmark-save-flag
3568 (setq bookmark-save-flag bmkp-last-save-flag-value)))
3569 (when msg-p (message (if bookmark-save-flag
3570 "Autosaving of current bookmark file is now ON"
3571 "Autosaving of current bookmark file is now OFF"))))
3572
3573 ;;;###autoload
3574 (defun bmkp-make-function-bookmark (bookmark-name function &optional msg-p) ; Not bound
3575 "Create a bookmark that invokes FUNCTION when \"jumped\" to.
3576 You are prompted for the bookmark name and the name of the function.
3577 Interactively, you are prompted for the bookmark and the function.
3578 Returns the new bookmark (internal record).
3579
3580 Non-interactively, non-nil optional arg MSG-P means display a status
3581 message."
3582 (interactive
3583 (let ((icicle-unpropertize-completion-result-flag t))
3584 (list (read-string "Bookmark: ")
3585 (completing-read "Function: " obarray 'functionp)
3586 t)))
3587 (bookmark-store bookmark-name `((filename . ,bmkp-non-file-filename)
3588 (position . 0)
3589 (function . ,(read function))
3590 (handler . bmkp-jump-function))
3591 nil (not msg-p))
3592 (let ((new (bmkp-bookmark-record-from-name bookmark-name 'NOERROR)))
3593 (unless (memq new bmkp-latest-bookmark-alist)
3594 (setq bmkp-latest-bookmark-alist (cons new bmkp-latest-bookmark-alist)))
3595 (bookmark-bmenu-surreptitiously-rebuild-list (not msg-p))
3596 new))
3597
3598 ;;;###autoload
3599 (defun bmkp-revert-bookmark-file (&optional msg-p) ; Same as `C-u g' in bookmark list (but not bound).
3600 "Revert to the bookmarks in the current bookmark file.
3601 This discards all modifications to bookmarks and the bookmark list
3602 \(e.g. added/deleted bookmarks).
3603 This has the same effect as using `C-u \\<bookmark-bmenu-mode-map>\\[bmkp-bmenu-refresh-menu-list]' in \
3604 buffer `*Bookmark List*'.
3605 Non-interactively, non-nil MSG-P means display a status message."
3606 (interactive "p")
3607 (if (and msg-p (not (yes-or-no-p (format "Revert to bookmarks saved in file `%s'? "
3608 bmkp-current-bookmark-file))))
3609 (error "OK - canceled")
3610 (bookmark-load bmkp-current-bookmark-file 'OVERWRITE msg-p) ; Do not let `bookmark-load' ask to save.
3611 (bmkp-refresh/rebuild-menu-list nil (not msg-p))))
3612
3613 ;;;###autoload
3614 (defun bmkp-switch-bookmark-file (file &optional batchp) ; Not bound and not used in the code now.
3615 "Switch to a different bookmark file, FILE.
3616 Return FILE. Interactively, you are prompted for FILE.
3617 Replace all bookmarks in the current bookmark list with those from the
3618 newly loaded FILE. Bookmarks are subsequently saved to FILE.
3619
3620 Optional arg BATCHP is passed to `bookmark-load'."
3621 (interactive
3622 (list (let* ((std-default (bmkp-default-bookmark-file))
3623 (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
3624 (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
3625 bookmark-default-file
3626 std-default)
3627 bmkp-last-bookmark-file)))
3628 (bmkp-read-bookmark-file-name "Switch to bookmark file: "
3629 (or (file-name-directory default) "~/")
3630 default t)))) ; Require that the file exist.
3631 (bookmark-load file t batchp)) ; Treat it interactively, if this command is called interactively.
3632
3633 ;;;###autoload
3634 (defun bmkp-switch-to-last-bookmark-file (&optional batchp) ; Not bound to any key, by default
3635 "Switch back to the last-used bookmark file.
3636 Replace all currently existing bookmarks with those newly loaded from
3637 the last-used file. Swap the values of `bmkp-last-bookmark-file' and
3638 `bmkp-current-bookmark-file'.
3639
3640 Optional arg BATCHP is passed to `bookmark-load'."
3641 (interactive)
3642 (bookmark-load (or bmkp-last-bookmark-file (bmkp-default-bookmark-file))
3643 t batchp)) ; Treat it interactively, if this command is called interactively.
3644
3645 ;;;###autoload
3646 (defun bmkp-switch-bookmark-file-create (file &optional batchp)
3647 ; Bound to `C-x p L', (`L' in bookmark list)
3648 "Switch to bookmark file FILE, creating it as empty if it does not exist.
3649 Return FILE. Interactively, you are prompted for FILE.
3650 Replace all bookmarks in the current bookmark list with those from the
3651 newly loaded FILE. Bookmarks are subsequently saved to FILE.
3652
3653 If there is no file with the name you provide (FILE), then create a
3654 new, empty bookmark file with that name and use that from now on.
3655 This empties the bookmark list. Interactively, you are required to
3656 confirm this.
3657
3658 Non-nil BATCHP is passed to `bookmark-load'."
3659 (interactive
3660 (list (let* ((std-default (bmkp-default-bookmark-file))
3661 (default (if (bmkp-same-file-p bmkp-current-bookmark-file bmkp-last-bookmark-file)
3662 (if (bmkp-same-file-p bmkp-current-bookmark-file std-default)
3663 bookmark-default-file
3664 std-default)
3665 bmkp-last-bookmark-file)))
3666 (bmkp-read-bookmark-file-name "Switch to bookmark file: "
3667 (or (file-name-directory default) "~/")
3668 default))))
3669 (let ((empty-p nil))
3670 (if (file-readable-p file)
3671 ;;; (if (or batchp (y-or-n-p (format "CONFIRM: `%s' as the current bookmark file? " file)))
3672 ;;; (bookmark-load file t batchp)
3673 ;;; (error "OK, canceled"))
3674 (bookmark-load file t batchp) ; Treat it interactively, if this command is called interactively.
3675 (setq empty-p t)
3676 (if (and (not batchp)
3677 (not (y-or-n-p (format "Create and use NEW, EMPTY bookmark file `%s'? " file))))
3678 (error "OK - canceled")
3679 (bmkp-empty-file file)
3680 (bookmark-load file t batchp))) ; Treat it interactively, if this command is called interactively.
3681 (unless batchp (message "Bookmark file is now %s`%s'" (if empty-p "EMPTY file " "") file)))
3682 file)
3683
3684 (defun bmkp-read-bookmark-file-name (&optional prompt dir default-filename require-match)
3685 "Read and return an (absolute) bookmark file name.
3686 PROMPT is the prompt to use (default: \"Use bookmark file: \").
3687
3688 DEFAULT-FILENAME is as for `read-file-name', except if nil then the
3689 default is `.emacs.bmk' in the current directory. Regardless what
3690 DEFAULT-FILENAME is, you can enter any file name.
3691
3692 The other args are the same as for `read-file-name'."
3693 (let ((insert-default-directory t)
3694 (icicle-unpropertize-completion-result-flag t)) ; For `read-file-name'.
3695 (expand-file-name
3696 (read-file-name (or prompt "Use bookmark file: ") dir (or default-filename
3697 (if (> emacs-major-version 22)
3698 (list ".emacs.bmk" bookmark-default-file)
3699 ".emacs.bmk"))
3700 require-match))))
3701
3702 ;;;###autoload
3703 (defun bmkp-empty-file (file &optional confirmp) ; Bound to `C-x p 0'
3704 "Empty the bookmark file FILE, or create FILE (empty) if it does not exist.
3705 In either case, FILE will become an empty bookmark file. Return FILE.
3706
3707 NOTE: If FILE already exists and you confirm emptying it, no check is
3708 made that it is in fact a bookmark file before emptying it.
3709 It is simply replaced by an empty bookmark file and saved.
3710
3711 This does NOT also make FILE the current bookmark file. To do that,
3712 use `\\[bmkp-switch-bookmark-file-create]' (`bmkp-switch-bookmark-file-create')."
3713 (interactive (list (let ((icicle-unpropertize-completion-result-flag t))
3714 (read-file-name "Create empty bookmark file: " "~/"))
3715 t))
3716 (setq file (expand-file-name file))
3717 (bookmark-maybe-load-default-file)
3718 (when (and confirmp (file-exists-p file)
3719 (not (y-or-n-p (format "CONFIRM: Empty the existing file `%s'? " file))))
3720 (error "OK - canceled"))
3721 (let ((bookmark-alist ()))
3722 (bookmark-write-file file (if (file-exists-p file)
3723 "Emptying bookmark file `%s'..."
3724 "Creating new, empty bookmark file `%s'...")))
3725 file)
3726
3727 ;;;###autoload
3728 (defun bmkp-crosshairs-highlight () ; Not bound
3729 "Call `crosshairs-highlight', unless the region is active.
3730 You can add this to hook `bookmark-after-jump-hook'.
3731 You need library `crosshairs.el' to use this command."
3732 (interactive)
3733 (when (> emacs-major-version 21) ; No-op for Emacs 20-21.
3734 (unless (condition-case nil (require 'crosshairs nil t) (error nil))
3735 (error "You need library `crosshairs.el' to use this command"))
3736 (unless mark-active
3737 (let ((crosshairs-overlay-priority (and (boundp 'bmkp-light-priorities)
3738 (1+ (apply #'max
3739 (mapcar #'cdr bmkp-light-priorities))))))
3740 (crosshairs-highlight)))))
3741
3742 ;;;###autoload
3743 (defun bmkp-choose-navlist-from-bookmark-list (bookmark-name &optional alist) ; Bound to `C-x p B'
3744 "Choose a bookmark-list bookmark and set the bookmark navigation list.
3745 The navigation-list variable, `bmkp-nav-alist', is set to the list of
3746 bookmarks that would be displayed by `bookmark-bmenu-list' (`C-x r l')
3747 for the chosen bookmark-list bookmark, sorted and filtered as
3748 appropriate.
3749
3750 Instead of choosing a bookmark-list bookmark, you can choose the
3751 pseudo-bookmark `CURRENT *Bookmark List*'. The bookmarks used for the
3752 navigation list are those that would be currently shown in the
3753 `*Bookmark List*' (even if the list is not currently displayed)."
3754 (interactive
3755 (let ((bookmark-alist (cons (bmkp-current-bookmark-list-state) (bmkp-bookmark-list-alist-only))))
3756 (list (bmkp-read-bookmark-for-type "bookmark-list" bookmark-alist nil nil
3757 'bmkp-bookmark-list-history "Choose ")
3758 bookmark-alist)))
3759 (let ((state (let ((bookmark-alist (or alist (cons (bmkp-current-bookmark-list-state)
3760 (bmkp-bookmark-list-alist-only)))))
3761 (bookmark-prop-get bookmark-name 'bookmark-list))))
3762 (let ((bmkp-sort-comparer (cdr (assq 'last-sort-comparer state)))
3763 (bmkp-reverse-sort-p (cdr (assq 'last-reverse-sort-p state)))
3764 (bmkp-reverse-multi-sort-p (cdr (assq 'last-reverse-multi-sort-p state)))
3765 (bmkp-bmenu-omitted-bookmarks (cdr (assq 'last-bmenu-omitted-bookmarks state)))
3766 (bmkp-bmenu-filter-function (cdr (assq 'last-bmenu-filter-function state)))
3767 (bmkp-bmenu-filter-pattern (or (cdr (assq 'last-bmenu-filter-pattern state)) ""))
3768 (bmkp-bmenu-title (cdr (assq 'last-bmenu-title state)))
3769 (bookmark-bmenu-toggle-filenames (cdr (assq 'last-bmenu-toggle-filenames state))))
3770 (setq bmkp-nav-alist (bmkp-sort-omit
3771 (if bmkp-bmenu-filter-function
3772 (funcall bmkp-bmenu-filter-function)
3773 (if (string= "CURRENT *Bookmark List*" bookmark-name)
3774 (or bmkp-latest-bookmark-alist bookmark-alist)
3775 bookmark-alist))
3776 (and (not (eq bmkp-bmenu-filter-function
3777 'bmkp-omitted-alist-only))
3778 bmkp-bmenu-omitted-bookmarks))
3779 bmkp-current-nav-bookmark (car bmkp-nav-alist))))
3780 (message "Bookmark navigation list is now %s"