(bcopy) Use memmove instead of memcpy.
[bpt/emacs.git] / lisp / bookmark.el
CommitLineData
b3bf02fa
RS
1;;; bookmark.el --- set bookmarks, jump to them later.
2
d22d6453 3;; Copyright (C) 1993 Free Software Foundation
b3bf02fa
RS
4
5;; Author: Karl Fogel <kfogel@cs.oberlin.edu>
8027e2ad 6;; Maintainer: Karl Fogel <kfogel@cs.oberlin.edu>
b3bf02fa 7;; Created: July, 1993
d23e2c3f 8;; Version: 2.5
b3bf02fa
RS
9;; Keywords: bookmarks, placeholders
10
11;; This file is part of GNU Emacs.
12
13;; GNU Emacs is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation; either version 2, or (at your option)
16;; any later version.
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
24;; along with GNU Emacs; see the file COPYING. If not, write to
25;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26
27;; Thanks to David Bremner <bremner@cs.sfu.ca> for thinking of and
28;; then implementing the bookmark-current-bookmark idea. He even
d23e2c3f 29;; sent *patches*, bless his soul...
b3bf02fa
RS
30
31;; Thanks to Gregory M. Saunders <saunders@cis.ohio-state.edu> for
32;; fixing and improving bookmark-time-to-save-p.
33
d23e2c3f
KF
34;; Thanks go to Andrew V. Klein <avk@rtsg.mot.com> for the code that
35;; sorts the alist before presenting it to the user (in list-bookmarks
36;; and the menu-bar).
37
d22d6453
RS
38;; And much thanks to David Hughes <djh@harston.cv.com> for many small
39;; suggestions and the code to implement them (like
40;; Bookmark-menu-check-position, and some of the Lucid compatibility
41;; stuff).
42
d23e2c3f
KF
43;; Kudos (whatever they are) go to Jim Blandy <jimb@cs.oberlin.edu>
44;; for his eminently sensible suggestion to separate bookmark-jump
45;; into bookmark-jump and bookmark-jump-noselect, which made many
46;; other things cleaner as well.
47
d22d6453
RS
48;; Thanks to Roland McGrath for encouragement and help with defining
49;; autoloads on the menu-bar.
50
d23e2c3f
KF
51;; Jonathan Stigelman <stig@key.amdahl.com> gave patches for default
52;; values in bookmark-jump and bookmark-set. Everybody please keep
53;; all the keystrokes they save thereby and send them to him at the
54;; end of each year :-) (No, seriously, thanks Jonathan!)
55
b3bf02fa
RS
56;; Based on info-bookmark.el, by Karl Fogel and Ken Olstad
57;; <olstad@msc.edu>.
58
59;; LCD Archive Entry:
60;; bookmark|Karl Fogel|kfogel@cs.oberlin.edu|
61;; Setting bookmarks in files or directories, jumping to them later.|
d23e2c3f 62;; 16-July-93|Version: 2.5|~/misc/bookmark.el.Z|
d22d6453
RS
63
64;; Enough with the credits already, get on to the good stuff:
b3bf02fa
RS
65
66;; FAVORITE CHINESE RESTAURANT:
67;; Boy, that's a tough one. Probably Hong Min, or maybe Emperor's
68;; Choice (both in Chicago's Chinatown). Well, both. How about you?
69
70;;; Commentary on code:
71
72;; bookmark alist format:
73;; (...
74;; (bookmark-name (filename
75;; string-in-front
76;; string-behind
77;; point))
78;; ...)
79;;
80;; bookmark-name is the string the user gives the bookmark and
81;; accesses it by from then on. filename is the location of the file
82;; in which the bookmark is set. string-in-front is a string of
83;; `bookmark-search-size' chars of context in front of the point the
84;; bookmark is set at, string-behind is the same thing after the
85;; point. bookmark-jump will search for string-behind and
86;; string-in-front in case the file has changed since the bookmark was
87;; set. It will attempt to place the user before the changes, if
88;; there were any.
11eb4275 89;;
d22d6453
RS
90;; The bookmark list is sorted lexically by default, but you can turn
91;; this off by setting bookmark-sort-flag to nil. If it is nil, then
92;; the list will be presented in the order it is recorded
93;; (chronologically), which is actually fairly useful as well.
b3bf02fa
RS
94
95;;; Code:
96
97;; Added for lucid emacs compatibility, db
98(or (fboundp 'defalias) (fset 'defalias 'fset))
99
d22d6453
RS
100;; suggested for lucid compatibility by david hughes:
101(or (fboundp 'frame-height) (fset 'frame-height 'screen-height))
102
103;; some people have C-x r set to rmail or whatever. We don't want to
104;; assume that C-x r is a prefix map just because it's distributed
105;; that way...
106;; These are the distribution keybindings suggested by RMS, everything
b3bf02fa 107;; else will be done with M-x or the menubar:
d22d6453 108;;;###autoload
5f5d794a
RS
109(if (or (symbolp (key-binding "\C-xr"))
110 (fboundp 'bookmark-set))
d22d6453
RS
111 nil
112 (progn (define-key ctl-x-map "rb" 'bookmark-jump)
113 (define-key ctl-x-map "rm" 'bookmark-set)
114 (define-key ctl-x-map "rl" 'list-bookmarks)))
b3bf02fa
RS
115
116;; define the map, so it can be bound by those who desire to do so:
117
d22d6453 118;;;###autoload
9aef3b21
RS
119(defvar bookmark-map nil
120 "Keymap containing bindings to bookmark functions.
121It is not bound to any key by default: to bind it
122so that you have a bookmark prefix, just use `global-set-key' and bind a
123key of your choice to `bookmark-map'. All interactive bookmark
b3bf02fa
RS
124functions have a binding in this keymap.")
125
d22d6453 126;;;###autoload
b3bf02fa
RS
127(define-prefix-command 'bookmark-map)
128
129;; Read the help on all of these functions for details...
d22d6453 130;;;###autoload
b3bf02fa 131(define-key bookmark-map "x" 'bookmark-set)
d22d6453
RS
132;;;###autoload
133(define-key bookmark-map "m" 'bookmark-set) ; "m" for "mark"
134;;;###autoload
b3bf02fa 135(define-key bookmark-map "j" 'bookmark-jump)
d22d6453
RS
136;;;###autoload
137(define-key bookmark-map "g" 'bookmark-jump) ; "g" for "go"
138;;;###autoload
b3bf02fa 139(define-key bookmark-map "i" 'bookmark-insert)
d22d6453
RS
140;;;###autoload
141(define-key bookmark-map "e" 'edit-bookmarks)
142;;;###autoload
b3bf02fa 143(define-key bookmark-map "f" 'bookmark-locate) ; "f" for "find"
d22d6453 144;;;###autoload
9aef3b21 145(define-key bookmark-map "r" 'bookmark-rename)
d22d6453 146;;;###autoload
b3bf02fa 147(define-key bookmark-map "d" 'bookmark-delete)
d22d6453 148;;;###autoload
b3bf02fa 149(define-key bookmark-map "l" 'bookmark-load)
d22d6453
RS
150;;;###autoload
151(define-key bookmark-map "w" 'bookmark-write)
152;;;###autoload
b3bf02fa
RS
153(define-key bookmark-map "s" 'bookmark-save)
154
7e2d009d
RS
155(defvar bookmark-alist ()
156 "Association list of bookmarks.
157You probably don't want to change the value of this alist yourself;
158instead, let the various bookmark functions do it for you.")
159
d22d6453
RS
160(defvar bookmarks-already-loaded nil)
161
b3bf02fa
RS
162;; just add the hook to make sure that people don't lose bookmarks
163;; when they kill Emacs, unless they don't want to save them.
d22d6453 164;;;###autoload
b3bf02fa
RS
165(add-hook 'kill-emacs-hook
166 (function
d22d6453
RS
167 (lambda () (and (featurep 'bookmark)
168 bookmark-alist
169 (bookmark-time-to-save-p t)
170 (bookmark-save)))))
b3bf02fa
RS
171
172;; more stuff added by db.
d22d6453 173
b3bf02fa 174(defvar bookmark-current-bookmark nil
9aef3b21
RS
175 "Name of bookmark most recently used in the current file.
176It is buffer local, used to make moving a bookmark forward
8027e2ad 177through a file easier.")
b3bf02fa
RS
178
179(make-variable-buffer-local 'bookmark-current-bookmark)
180
181(defvar bookmark-save-flag t
9aef3b21
RS
182 "*Controls when Emacs saves bookmarks to a file.
183--> Nil means never save bookmarks, except when `bookmark-save' is
184 explicitly called \(\\[bookmark-save]\).
185--> t means save bookmarks when Emacs is killed.
186--> Otherise, it should be a number that is the frequency with which
187 the bookmark list is saved \(i.e.: the number of times which
188 Emacs' bookmark list may be modified before it is automatically
189 saved.\). If it is a number, Emacs will also automatically save
190 bookmarks when it is killed.
b3bf02fa
RS
191
192Therefore, the way to get it to save every time you make or delete a
193bookmark is to set this variable to 1 \(or 0, which produces the same
194behavior.\)
195
196To specify the file in which to save them, modify the variable
9aef3b21 197bookmark-file, which is `~/.emacs-bkmrks' by default.")
b3bf02fa
RS
198
199(defvar bookmark-alist-modification-count 0
9aef3b21 200 "Number of modifications to bookmark list since it was last saved.")
b3bf02fa
RS
201
202(defvar bookmark-file "~/.emacs-bkmrks"
203 "*File in which to save bookmarks by default.")
204
d22d6453
RS
205(defvar bookmark-version-control 'nospecial
206 "This variable controls whether or not to make numbered backups of
207the master bookmark file. It can have four values: t, nil, never, and
208nospecial. The first three have the same meaning that they do for the
209variable version-control, and the final value nospecial means just use
210the value of version-control.")
211
b3bf02fa 212(defvar bookmark-completion-ignore-case t
9aef3b21 213 "*Non-nil means bookmark functions ignore case in completion.")
b3bf02fa 214
d22d6453
RS
215(defvar bookmark-sort-flag t
216 "*Non-nil means that bookmarks will be displayed sorted by bookmark
217name. Otherwise they will be displayed in LIFO order (that is, most
218recently set ones come first, oldest ones come last).")
219
9aef3b21
RS
220(defvar bookmark-search-size 500
221 "Length of the context strings recorded on either side of a bookmark.")
b3bf02fa 222
b3bf02fa
RS
223(defvar bookmark-current-point 0)
224(defvar bookmark-yank-point 0)
225(defvar bookmark-current-buffer nil)
226
d22d6453 227;;;###autoload
b3bf02fa 228(defun bookmark-set (&optional parg)
9aef3b21
RS
229 "Set a bookmark named NAME inside a file.
230With prefix arg, will not overwrite a bookmark that has the same name
231as NAME if such a bookmark already exists, but instead will \"push\"
232the new bookmark onto the bookmark alist. Thus the most recently set
233bookmark with name NAME would be the one in effect at any given time,
234but the others are still there, should you decide to delete the most
235recent one.
b3bf02fa
RS
236
237To yank words from the text of the buffer and use them as part of the
9aef3b21 238bookmark name, type C-w while setting a bookmark. Successive C-w's
b3bf02fa
RS
239yank successive words.
240
241Typing C-v inserts the name of the current file being visited. Typing
242C-u inserts the name of the last bookmark used in the buffer \(as an
243aid in using a single bookmark name to track your progress through a
244large file\). If no bookmark was used, then C-u behaves like C-v and
245inserts the name of the file being visited.
246
247Use \\[bookmark-delete] to remove bookmarks \(you give it a name,
248and it removes only the first instance of a bookmark with that name from
249the list of bookmarks.\)"
250 (interactive "P")
251 (if (not (bookmark-buffer-file-name))
252 (error "Buffer not visiting a file or directory."))
d22d6453 253 (bookmark-try-default-file)
b3bf02fa
RS
254 (setq bookmark-current-point (point))
255 (setq bookmark-yank-point (point))
256 (setq bookmark-current-buffer (current-buffer))
d22d6453
RS
257 (let* ((default (or bookmark-current-bookmark
258 (buffer-name (current-buffer))))
259 (str
260 (read-from-minibuffer
261 (format "Set bookmark (%s): " default)
262 nil
263 (let ((now-map (copy-keymap minibuffer-local-map)))
264 (progn (define-key now-map "\C-w"
265 'bookmark-yank-word)
266 (define-key now-map "\C-v"
267 'bookmark-insert-current-file-name)
268 (define-key now-map "\C-u"
269 'bookmark-insert-current-bookmark))
270 now-map))))
271 (and (string-equal str "") (setq str default))
b3bf02fa
RS
272 (progn
273 (bookmark-make parg str)
d22d6453
RS
274 (setq bookmark-current-bookmark str)
275 (if (get-buffer "*Bookmark List*") ;rebuild the bookmark list
276 (save-excursion
277 (save-window-excursion
278 (list-bookmarks))))
b3bf02fa
RS
279 (goto-char bookmark-current-point))))
280
281(defun bookmark-insert-current-bookmark ()
282 ;; insert this buffer's value of bookmark-current-bookmark, default
283 ;; to file name if it's nil.
284 (interactive)
285 (let ((str
286 (save-excursion
287 (set-buffer bookmark-current-buffer)
288 bookmark-current-bookmark)))
289 (if str (insert str) (bookmark-insert-current-file-name))))
290
291(defun bookmark-insert-current-file-name ()
292 ;; insert the name (sans path) of the current file into the bookmark
293 ;; name that is being set.
294 (interactive)
295 (let ((str (save-excursion
d22d6453
RS
296 (set-buffer bookmark-current-buffer)
297 (bookmark-buffer-file-name))))
b3bf02fa
RS
298 (insert (substring
299 str
300 (1+ (string-match
301 "\\(/[^/]*\\)/*$"
302 str))))))
303
304(defun bookmark-yank-word ()
305 (interactive)
306 ;; get the next word from the buffer and append it to the name of
307 ;; the bookmark currently being set.
308 (let ((string (save-excursion
d22d6453
RS
309 (set-buffer bookmark-current-buffer)
310 (goto-char bookmark-yank-point)
311 (buffer-substring
312 (point)
313 (save-excursion
314 (forward-word 1)
315 (setq bookmark-yank-point (point)))))))
b3bf02fa
RS
316 (insert string)))
317
318(defun bookmark-make (parg str)
319 (if (and (assoc str bookmark-alist) (not parg))
320 ;; already existing boookmark under that name and
321 ;; no prefix arg means just overwrite old bookmark
322 (setcdr (assoc str bookmark-alist)
323 (list (bookmark-make-cell)))
324
325 ;; otherwise just cons it onto the front (either the bookmark
326 ;; doesn't exist already, or there is no prefix arg. In either
327 ;; case, we want the new bookmark consed onto the alist...)
328
329 (setq bookmark-alist
330 (cons
331 (list str
332 (bookmark-make-cell))
333 bookmark-alist)))
334 ;; Added by db
335 (setq bookmark-current-bookmark str)
336 (setq bookmark-alist-modification-count
337 (1+ bookmark-alist-modification-count))
338 (if (bookmark-time-to-save-p)
339 (bookmark-save)))
340
341(defun bookmark-make-cell ()
342 ;; make the cell that is the cdr of a bookmark alist element. It
343 ;; looks like this:
344 ;; (filename search-forward-str search-back-str point)
345 (list
346 (bookmark-buffer-file-name)
347 (if (>= (- (point-max) (point)) bookmark-search-size)
348 (buffer-substring
349 (point)
350 (+ (point) bookmark-search-size))
351 nil)
352 (if (>= (- (point) (point-min)) bookmark-search-size)
353 (buffer-substring
354 (point)
355 (- (point) bookmark-search-size))
356 nil)
357 (point)))
358
359(defun bookmark-buffer-file-name ()
360 (or
361 buffer-file-name
362 (if (and (boundp 'dired-directory) dired-directory)
363 (if (stringp dired-directory)
364 dired-directory
365 (car dired-directory)))))
366
367(defun bookmark-try-default-file ()
d22d6453
RS
368 (and (not bookmarks-already-loaded)
369 (null bookmark-alist)
370 (file-readable-p (expand-file-name bookmark-file))
371 (progn
372 (bookmark-load bookmark-file t t)
373 (setq bookmarks-already-loaded t))))
374
375(defun bookmark-maybe-sort-alist ()
376 ;;Return the bookmark-alist for display. If the bookmark-sort-flag
377 ;;is non-nil, then return a sorted copy of the alist.
378 (if bookmark-sort-flag
379 (setq bookmark-alist
380 (sort (copy-alist bookmark-alist)
381 (function
382 (lambda (x y) (string-lessp (car x) (car y))))))))
383
384;;;###autoload
b3bf02fa 385(defun bookmark-jump (str)
9aef3b21
RS
386 "Jump to bookmark BOOKMARK (a point in some file).
387You may have a problem using this function if the value of variable
388`bookmark-alist' is nil. If that happens, you need to load in some
389bookmarks. See help on function `bookmark-load' for more about
d22d6453
RS
390this.
391
392If the file pointed to by BOOKMARK no longer exists, you will be asked
393if you wish to give the bookmark a new location, and bookmark-jump
394will then jump to the new location, as well as recording it in place
395of the old one in the permanent bookmark record."
396 (interactive (progn (bookmark-try-default-file)
397 (let* ((completion-ignore-case
398 bookmark-completion-ignore-case)
399 (default
400 (or (and
401 (assoc bookmark-current-bookmark
402 bookmark-alist)
403 bookmark-current-bookmark)
404 (and (assoc (buffer-name (current-buffer))
405 bookmark-alist)
406 (buffer-name (current-buffer)))))
407 (str
408 (completing-read
409 (if default
410 (format "Jump to bookmark (%s): "
411 default)
412 "Jump to bookmark: ")
413 bookmark-alist
414 nil
415 0)))
416 (and (string-equal "" str)
417 (setq str default))
418 (list str))))
419 (let ((cell (bookmark-jump-noselect str)))
420 (and cell
421 (switch-to-buffer (car cell))
422 (goto-char (cdr cell)))))
423
424(defun bookmark-jump-noselect (str)
425 ;; a leetle helper for bookmark-jump :-)
426 ;; returns (BUFFER . POINT)
427 (let ((whereto-list (car (cdr (assoc str bookmark-alist)))))
428 (let* ((file (expand-file-name (car whereto-list)))
429 (orig-file file)
430 (forward-str (car (cdr whereto-list)))
431 (behind-str (car (cdr (cdr whereto-list))))
432 (place (car (cdr (cdr (cdr whereto-list))))))
433 (if (or
434 (file-exists-p file)
435 ;; else try some common compression extensions
436 ;; and Emacs better handle it right!
437 (setq file
438 (or
439 (let ((altname (concat file ".Z")))
440 (and (file-exists-p altname)
441 altname))
442 (let ((altname (concat file ".gz")))
443 (and (file-exists-p altname)
444 altname))
445 (let ((altname (concat file ".z")))
446 (and (file-exists-p altname)
447 altname)))))
448 (save-excursion
449 (set-buffer (find-file-noselect file))
450 (goto-char place)
451 ;; Go searching forward first. Then, if forward-str exists and
452 ;; was found in the file, we can search backward for behind-str.
453 ;; Rationale is that if text was inserted between the two in the
454 ;; file, it's better to be put before it so you can read it,
455 ;; rather than after and remain perhaps unaware of the changes.
456 (if forward-str
457 (if (search-forward forward-str (point-max) t)
458 (backward-char bookmark-search-size)))
459 (if behind-str
460 (if (search-backward behind-str (point-min) t)
461 (forward-char bookmark-search-size)))
462 ;; added by db
463 (setq bookmark-current-bookmark str)
464 (cons (current-buffer) (point)))
465 (progn
466 (ding)
467 (if (y-or-n-p (concat (file-name-nondirectory orig-file)
468 " nonexistent. Relocate \""
469 str
470 "\"? "))
471 (progn
472 (bookmark-relocate str)
473 ;; gasp! It's a recursive function call in Emacs Lisp!
474 (bookmark-jump-noselect str))
475 (message
476 "Bookmark not relocated, but deleting it would be a good idea.")
477 nil))))))
478
479;;;###autoload
480(defun bookmark-relocate (str)
481 "Relocate BOOKMARK -- prompts for a filename, and makes an already
482existing bookmark point to that file, instead of the one it used to
483point at. Useful when a file has been renamed after a bookmark was
484set in it."
11eb4275
RS
485 (interactive (let ((completion-ignore-case
486 bookmark-completion-ignore-case))
d22d6453
RS
487 (progn (bookmark-try-default-file)
488 (list (completing-read
489 "Bookmark to relocate: "
490 bookmark-alist
491 nil
492 0)))))
493 (let* ((bmrk (assoc str bookmark-alist))
494 (bmrk-filename (car (car (cdr bmrk))))
495 (newloc (expand-file-name
496 (read-file-name
497 (format "Relocate %s to: " str)
498 (file-name-directory bmrk-filename)))))
499 (setcar (car (cdr bmrk)) newloc)))
500
501;;;###autoload
502(defun bookmark-locate (str &optional no-insertion)
503 "Insert the name of the file associated with BOOKMARK.
504Optional second arg NO-INSERTION means merely return the filename as a
505string."
506 (interactive (let ((completion-ignore-case
507 bookmark-completion-ignore-case))
508 (progn (bookmark-try-default-file)
509 (list (completing-read
510 "Insert bookmark location: "
511 bookmark-alist
512 nil
513 0)))))
514 (let ((where (car (car (cdr (assoc str bookmark-alist))))))
515 (if no-insertion
516 where
517 (insert where))))
518
519;;;###autoload
9aef3b21 520(defun bookmark-rename (old &optional new)
d22d6453
RS
521 "Change the name of OLD-BOOKMARK to NEWNAME.
522If called from keyboard, prompts for OLD-BOOKMARK and NEWNAME.
523If called from menubar, OLD-BOOKMARK is selected from a menu, and
524prompts for NEWNAME.
525If called from Lisp, prompts for NEWNAME if only OLD-BOOKMARK was
526passed as an argument. If called with two strings, then no prompting
527is done. You must pass at least OLD-BOOKMARK when calling from Lisp.
9aef3b21
RS
528
529While you are entering the new name, consecutive C-w's insert
530consectutive words from the text of the buffer into the new bookmark
531name, and C-v inserts the name of the file."
11eb4275
RS
532 (interactive (let ((completion-ignore-case
533 bookmark-completion-ignore-case))
d22d6453
RS
534 (progn (bookmark-try-default-file)
535 (list (completing-read "Old bookmark name: "
536 bookmark-alist
537 nil
538 0)))))
b3bf02fa
RS
539 (progn
540 (setq bookmark-current-point (point))
541 (setq bookmark-yank-point (point))
542 (setq bookmark-current-buffer (current-buffer))
543 (let ((cell (assoc old bookmark-alist))
544 (str
9aef3b21
RS
545 (or new ; use second arg, if non-nil
546 (read-from-minibuffer
547 "New name: "
548 nil
549 (let ((now-map (copy-keymap minibuffer-local-map)))
550 (progn (define-key now-map "\C-w"
551 'bookmark-yank-word)
552 (define-key now-map "\C-v"
553 'bookmark-insert-current-file-name))
554 now-map)))))
b3bf02fa
RS
555 (progn
556 (setcar cell str)
557 (setq bookmark-current-bookmark str)
d22d6453
RS
558 (if (get-buffer "*Bookmark List*")
559 (save-excursion (save-window-excursion (list-bookmarks))))
b3bf02fa
RS
560 (setq bookmark-alist-modification-count
561 (1+ bookmark-alist-modification-count))
562 (if (bookmark-time-to-save-p)
563 (bookmark-save))))))
564
d22d6453 565;;;###autoload
b3bf02fa 566(defun bookmark-insert (str)
9aef3b21
RS
567 "Insert the text of the file pointed to by bookmark BOOKMARK.
568You may have a problem using this function if the value of variable
569`bookmark-alist' is nil. If that happens, you need to load in some
570bookmarks. See help on function `bookmark-load' for more about
8027e2ad 571this."
11eb4275
RS
572 (interactive (let ((completion-ignore-case
573 bookmark-completion-ignore-case))
d22d6453
RS
574 (progn (bookmark-try-default-file)
575 (list (completing-read
576 "Insert bookmark contents: "
577 bookmark-alist
578 nil
579 0)))))
580 (let ((orig-point (point))
581 (str-to-insert
582 (save-excursion
583 (set-buffer (car (bookmark-jump-noselect str)))
584 (buffer-substring (point-min) (point-max)))))
585 (insert str-to-insert)
586 (push-mark)
587 (goto-char orig-point)))
588
589;;;###autoload
b3bf02fa 590(defun bookmark-delete (str)
9aef3b21
RS
591 "Delete the bookmark named NAME from the bookmark list.
592Removes only the first instance of a bookmark with that name. If
593there are one or more other bookmarks with the same name, they will
594not be deleted. Defaults to the \"current\" bookmark \(that is, the
595one most recently used in this file, if any\)."
b3bf02fa
RS
596 (interactive (let ((completion-ignore-case
597 bookmark-completion-ignore-case))
d22d6453
RS
598 (progn (bookmark-try-default-file)
599 (list
600 (completing-read
601 "Delete bookmark: "
602 bookmark-alist
603 nil
604 0
605 bookmark-current-bookmark)))))
11eb4275
RS
606 (let ((will-go (assoc str bookmark-alist)))
607 (setq bookmark-alist (delq will-go bookmark-alist))
608 ;; Added by db, nil bookmark-current-bookmark if the last
609 ;; occurence has been deleted
b3bf02fa 610 (or (assoc bookmark-current-bookmark bookmark-alist)
11eb4275 611 (setq bookmark-current-bookmark nil)))
d22d6453
RS
612 (if (get-buffer "*Bookmark List*")
613 (save-excursion (save-window-excursion (list-bookmarks))))
11eb4275
RS
614 (setq bookmark-alist-modification-count
615 (1+ bookmark-alist-modification-count))
616 (if (bookmark-time-to-save-p)
617 (bookmark-save)))
b3bf02fa
RS
618
619(defun bookmark-time-to-save-p (&optional last-time)
620 ;; By Gregory M. Saunders <saunders@cis.ohio-state.edu>
621 ;; finds out whether it's time to save bookmarks to a file, by
622 ;; examining the value of variable bookmark-save-flag, and maybe
623 ;; bookmark-alist-modification-count. Returns t if they should be
624 ;; saved, nil otherwise. if last-time is non-nil, then this is
625 ;; being called when emacs is killed.
626 (cond (last-time
627 (and (> bookmark-alist-modification-count 0)
628 bookmark-save-flag))
629 ((numberp bookmark-save-flag)
630 (>= bookmark-alist-modification-count bookmark-save-flag))
631 (t
632 nil)))
633
d22d6453 634;;;###autoload
b3bf02fa 635(defun bookmark-write ()
d22d6453
RS
636 "Write bookmarks to a file \(for which the user will be prompted
637interactively\). Don't use this in Lisp programs; use bookmark-save
638instead."
b3bf02fa 639 (interactive)
d22d6453 640 (bookmark-try-default-file)
b3bf02fa
RS
641 (bookmark-save t))
642
d22d6453 643;;;###autoload
11eb4275 644(defun bookmark-save (&optional parg file)
9aef3b21
RS
645 "Save currently defined bookmarks.
646Saves by default in the file defined by the variable
647`bookmark-file'. With a prefix arg, save it in file FILE.
b3bf02fa
RS
648
649If you are calling this from Lisp, the two arguments are PREFIX-ARG
650and FILE, and if you just want it to write to the default file, then
651pass no arguments. Or pass in nil and FILE, and it will save in FILE
652instead. If you pass in one argument, and it is non-nil, then the
653user will be interactively queried for a file to save in.
654
11eb4275 655When you want to load in the bookmarks from a file, use
9aef3b21 656\`bookmark-load\', \\[bookmark-load]. That function will prompt you
11eb4275 657for a file, defaulting to the file defined by variable
9aef3b21 658`bookmark-file'."
b3bf02fa 659 (interactive "P")
d22d6453 660 (bookmark-try-default-file)
b3bf02fa
RS
661 (cond
662 ((and (null parg) (null file))
663 ;;whether interactive or not, write to default file
664 (bookmark-write-file bookmark-file))
665 ((and (null parg) file)
666 ;;whether interactive or not, write to given file
667 (bookmark-write-file file))
668 ((and parg (not file))
669 ;;have been called interactively w/ prefix arg
670 (let ((file (read-file-name "File to save bookmarks in: ")))
671 (bookmark-write-file file)))
672 (t ; someone called us with prefix-arg *and* a file, so just write to file
673 (bookmark-write-file file)))
674 ;; signal that we have synced the bookmark file by setting this to
675 ;; 0. If there was an error at any point before, it will not get
676 ;; set, which is what we want.
677 (setq bookmark-alist-modification-count 0))
678
679(defun bookmark-write-file (file)
680 (save-excursion
d22d6453
RS
681 (save-window-excursion
682 (if (>= baud-rate 9600)
683 (message (format "Saving bookmarks to file %s." file)))
186a7127 684 (set-buffer (let ((enable-local-variables nil))
d23e2c3f 685 (find-file-noselect file)))
d22d6453
RS
686 (goto-char (point-min))
687 (delete-region (point-min) (point-max))
688 (print bookmark-alist (current-buffer))
689 (let ((version-control
690 (cond
691 ((null bookmark-version-control) nil)
692 ((eq 'never bookmark-version-control) 'never)
693 ((eq 'nospecial bookmark-version-control) version-control)
694 (t
695 t))))
696 (write-file file)
697 (kill-buffer (current-buffer))))))
698
699;;;###autoload
b3bf02fa 700(defun bookmark-load (file &optional revert no-msg)
9aef3b21
RS
701 "Load bookmarks from FILE (which must be in bookmark format).
702Appends loaded bookmarks to the front of the list of bookmarks. If
703optional second argument REVERT is non-nil, existing bookmarks are
704destroyed. Optional third arg NO-MSG means don't display any messages
705while loading.
b3bf02fa
RS
706
707If you load a file that doesn't contain a proper bookmark alist, you
9aef3b21 708will corrupt Emacs's bookmark list. Generally, you should only load
b3bf02fa 709in files that were created with the bookmark functions in the first
9aef3b21 710place. Your own personal bookmark file, `~/.emacs-bkmrks', is
8027e2ad 711maintained automatically by Emacs; you shouldn't need to load it
11eb4275 712explicitly."
b3bf02fa 713 (interactive
d22d6453
RS
714 (progn (bookmark-try-default-file)
715 (list (read-file-name
716 (format "Load bookmarks from: (%s) "
717 bookmark-file)
718 ;;Default might not be used often,
719 ;;but there's no better default, and
720 ;;I guess it's better than none at all.
721 "~/" bookmark-file 'confirm))))
b3bf02fa
RS
722 (setq file (expand-file-name file))
723 (if (file-readable-p file)
724 (save-excursion
d22d6453
RS
725 (save-window-excursion
726 (if (and (null no-msg) (>= baud-rate 9600))
727 (message (format "Loading bookmarks from %s..." file)))
186a7127 728 (set-buffer (let ((enable-local-variables nil))
d23e2c3f 729 (find-file-noselect file)))
d22d6453
RS
730 (goto-char (point-min))
731 (let ((blist (car (read-from-string
732 (buffer-substring (point-min) (point-max))))))
733 (if (listp blist)
734 (progn
735 (if (not revert)
736 (setq bookmark-alist-modification-count
737 (1+ bookmark-alist-modification-count))
738 (setq bookmark-alist-modification-count 0))
739 (setq bookmark-alist
740 (append blist (if (not revert) bookmark-alist)))
741 (if (get-buffer "*Bookmark List*")
742 (save-excursion (list-bookmarks))))
743 (error (format "Invalid bookmark list in %s." file))))
744 (kill-buffer (current-buffer)))
745 (if (and (null no-msg) (>= baud-rate 9600))
746 (message (format "Loading bookmarks from %s... done" file))))
b3bf02fa
RS
747 (error (format "Cannot read bookmark file %s." file))))
748
d22d6453
RS
749;;;; bookmark-menu-mode stuff ;;;;
750
751(defvar Bookmark-menu-bookmark-column nil)
752
753(defvar Bookmark-menu-hidden-bookmarks ())
754
755(defvar Bookmark-menu-file-column 30
756 "*Column at which to display filenames in a buffer listing bookmarks.
757You can toggle whether files are shown with \\<Bookmark-menu-mode-map>\\[Bookmark-menu-toggle-filenames].")
758
759(defvar Bookmark-menu-toggle-filenames t
760 "*Non-nil means show filenames when listing bookmarks.
761This may result in truncated bookmark names. To disable this, put the
762following in your .emacs:
763
764\(setq Bookmark-menu-toggle-filenames nil\)")
765
766(defvar Bookmark-menu-mode-map nil)
767
768(if Bookmark-menu-mode-map
769 nil
770 (setq Bookmark-menu-mode-map (make-keymap))
771 (suppress-keymap Bookmark-menu-mode-map t)
772 (define-key Bookmark-menu-mode-map "q" 'Bookmark-menu-quit)
773 (define-key Bookmark-menu-mode-map "v" 'Bookmark-menu-select)
774 (define-key Bookmark-menu-mode-map "w" 'Bookmark-menu-locate)
775 (define-key Bookmark-menu-mode-map "2" 'Bookmark-menu-2-window)
776 (define-key Bookmark-menu-mode-map "1" 'Bookmark-menu-1-window)
777 (define-key Bookmark-menu-mode-map "j" 'Bookmark-menu-this-window)
778 (define-key Bookmark-menu-mode-map "f" 'Bookmark-menu-this-window)
779 (define-key Bookmark-menu-mode-map "o" 'Bookmark-menu-other-window)
780 (define-key Bookmark-menu-mode-map "\C-o" 'Bookmark-menu-switch-other-window)
781 (define-key Bookmark-menu-mode-map "s" 'Bookmark-menu-save)
782 (define-key Bookmark-menu-mode-map "k" 'Bookmark-menu-delete)
783 (define-key Bookmark-menu-mode-map "\C-d" 'Bookmark-menu-delete-backwards)
784 (define-key Bookmark-menu-mode-map "x" 'Bookmark-menu-execute)
785 (define-key Bookmark-menu-mode-map "\C-k" 'Bookmark-menu-delete)
786 (define-key Bookmark-menu-mode-map "d" 'Bookmark-menu-delete)
787 (define-key Bookmark-menu-mode-map " " 'next-line)
788 (define-key Bookmark-menu-mode-map "n" 'next-line)
789 (define-key Bookmark-menu-mode-map "p" 'previous-line)
790 (define-key Bookmark-menu-mode-map "\177" 'Bookmark-menu-backup-unmark)
791 (define-key Bookmark-menu-mode-map "?" 'describe-mode)
792 (define-key Bookmark-menu-mode-map "u" 'Bookmark-menu-unmark)
793 (define-key Bookmark-menu-mode-map "m" 'Bookmark-menu-mark)
794 (define-key Bookmark-menu-mode-map "l" 'Bookmark-menu-load)
795 (define-key Bookmark-menu-mode-map "r" 'Bookmark-menu-rename)
796 (define-key Bookmark-menu-mode-map "t" 'Bookmark-menu-toggle-filenames))
797
798;; Bookmark Menu mode is suitable only for specially formatted data.
799(put 'Bookmark-menu-mode 'mode-class 'special)
800
801;; need to display whether or not bookmark exists as a buffer in flag
802;; column.
803
804;; Format:
805;; FLAGS BOOKMARK (/FILE/NAME/HERE/WHAT/REGEXP/TO/USE?)
806;; goto bookmark-column and then search till "(/[^)]*)$" or "(/.*)$" ?
807
808;;;###autoload
809(defalias 'edit-bookmarks 'list-bookmarks)
810
811;;;###autoload
812(defun list-bookmarks ()
813 "Display a list of existing bookmarks.
814The list is displayed in a buffer named `*Bookmark List*'.
815The leftmost column displays a D if the bookmark is flagged for
816deletion, or > if it is flagged for displaying."
817 (interactive)
818 (bookmark-try-default-file)
819 (switch-to-buffer (get-buffer-create "*Bookmark List*"))
820 (let ((buffer-read-only nil))
821 (delete-region (point-max) (point-min))
822 (goto-char (point-min)) ;sure are playing it safe...
823 (insert "% Bookmark\n- --------\n")
824 (bookmark-maybe-sort-alist)
825 (let ((lst bookmark-alist))
826 (while lst
827 (insert
828 (concat " " (car (car lst)) "\n"))
829 (setq lst (cdr lst)))))
830 (goto-char (point-min))
831 (forward-line 2)
832 (bookmark-menu-mode)
833 (if Bookmark-menu-toggle-filenames
834 (Bookmark-menu-toggle-filenames t)))
835
836(defun bookmark-menu-mode ()
837 "Major mode for editing a list of bookmarks.
838Each line describes one of the bookmarks in Emacs.
839Letters do not insert themselves; instead, they are commands.
840\\<Bookmark-menu-mode-map>
841\\[Bookmark-menu-mark] -- mark bookmark to be displayed.
842\\[Bookmark-menu-select] -- select bookmark of line point is on.
843 Also show bookmarks marked using m in other windows.
844\\[Bookmark-menu-toggle-filenames] -- toggle displaying of filenames (they may obscure long bookmark names).
845\\[Bookmark-menu-locate] -- display (in minibuffer) location of this bookmark.
846\\[Bookmark-menu-1-window] -- select this bookmark in full-frame window.
847\\[Bookmark-menu-2-window] -- select this bookmark in one window,
848 together with bookmark selected before this one in another window.
849\\[Bookmark-menu-this-window] -- select this bookmark in place of the bookmark menu buffer.
850\\[Bookmark-menu-other-window] -- select this bookmark in another window,
851 so the bookmark menu bookmark remains visible in its window.
852\\[Bookmark-menu-switch-other-window] -- switch the other window to this bookmark.
853\\[Bookmark-menu-rename] -- rename this bookmark \(prompts for new name\).
854\\[Bookmark-menu-delete] -- mark this bookmark to be deleted, and move down.
855\\[Bookmark-menu-delete-backwards] -- mark this bookmark to be deleted, and move up.
856\\[Bookmark-menu-execute] -- delete marked bookmarks.
857\\[Bookmark-menu-save] -- save the current bookmark list in the default file.
858 With a prefix arg, prompts for a file to save in.
859\\[Bookmark-menu-load] -- load in a file of bookmarks (prompts for file.)
860\\[Bookmark-menu-unmark] -- remove all kinds of marks from current line.
861 With prefix argument, also move up one line.
862\\[Bookmark-menu-backup-unmark] -- back up a line and remove marks."
863 (kill-all-local-variables)
864 (use-local-map Bookmark-menu-mode-map)
865 (setq truncate-lines t)
866 (setq buffer-read-only t)
867 (setq major-mode 'bookmark-menu-mode)
868 (setq mode-name "Bookmark Menu")
869 (run-hooks 'bookmark-menu-mode-hook))
870
871(defun Bookmark-menu-toggle-filenames (&optional parg)
872 "Toggle whether filenames are shown in the bookmark list.
873Optional argument SHOW means show them unconditionally."
874 (interactive)
875 (cond
876 (parg
877 (setq Bookmark-menu-toggle-filenames nil)
878 (Bookmark-menu-show-filenames)
879 (setq Bookmark-menu-toggle-filenames t))
880 (Bookmark-menu-toggle-filenames
881 (Bookmark-menu-hide-filenames)
882 (setq Bookmark-menu-toggle-filenames nil))
883 (t
884 (Bookmark-menu-show-filenames)
885 (setq Bookmark-menu-toggle-filenames t))))
886
887(defun Bookmark-menu-show-filenames (&optional force)
888 (if (and (not force) Bookmark-menu-toggle-filenames)
889 nil ;already shown, so do nothing
890 (save-excursion
891 (save-window-excursion
892 (goto-char (point-min))
893 (forward-line 2)
894 (setq Bookmark-menu-hidden-bookmarks ())
895 (let ((buffer-read-only nil))
896 (while (< (point) (point-max))
897 (let ((bmrk (Bookmark-menu-bookmark)))
898 (setq Bookmark-menu-hidden-bookmarks
899 (cons bmrk Bookmark-menu-hidden-bookmarks))
900 (move-to-column Bookmark-menu-file-column t)
901 (delete-region (point) (progn (end-of-line) (point)))
902 (insert " ")
903 (bookmark-locate bmrk)
904 (forward-line 1))))))))
905
906(defun Bookmark-menu-hide-filenames (&optional force)
907 (if (and (not force) Bookmark-menu-toggle-filenames)
908 ;; nothing to hide if above is nil
909 (save-excursion
910 (save-window-excursion
911 (goto-char (point-min))
912 (forward-line 2)
913 (setq Bookmark-menu-hidden-bookmarks
914 (nreverse Bookmark-menu-hidden-bookmarks))
915 (save-excursion
916 (goto-char (point-min))
917 (search-forward "Bookmark")
918 (backward-word 1)
919 (setq Bookmark-menu-bookmark-column (current-column)))
920 (save-excursion
921 (let ((buffer-read-only nil))
922 (while Bookmark-menu-hidden-bookmarks
923 (move-to-column Bookmark-menu-bookmark-column t)
924 (kill-line)
925 (insert (car Bookmark-menu-hidden-bookmarks))
926 (setq Bookmark-menu-hidden-bookmarks
927 (cdr Bookmark-menu-hidden-bookmarks))
928 (forward-line 1))))))))
929
930;; if you look at this next function from far away, it resembles a
931;; gun. But only with this comment above...
932(defun Bookmark-menu-check-position ()
933 ;; Returns t if on a line with a bookmark.
934 ;; Otherwise, repositions and returns t.
935 ;; written by David Hughes <djh@harston.cv.com>
936 ;; Mucho thanks, David! -karl
937 (cond ((< (count-lines (point-min) (point)) 2)
938 (goto-char (point-min))
939 (forward-line 2)
940 t)
941 ((and (bolp) (eobp))
942 (beginning-of-line 0)
943 t)
944 (t
945 t)))
946
947(defun Bookmark-menu-bookmark ()
948 ;; return a string which is bookmark of this line.
949 (if (Bookmark-menu-check-position)
950 (save-excursion
951 (save-window-excursion
952 (goto-char (point-min))
953 (search-forward "Bookmark")
954 (backward-word 1)
955 (setq Bookmark-menu-bookmark-column (current-column)))))
956 (if Bookmark-menu-toggle-filenames
957 (Bookmark-menu-hide-filenames))
958 (save-excursion
959 (save-window-excursion
960 (beginning-of-line)
961 (forward-char Bookmark-menu-bookmark-column)
962 (prog1
963 (buffer-substring (point)
964 (progn
965 (end-of-line)
966 (point)))
967 ;; well, this is certainly crystal-clear:
968 (if Bookmark-menu-toggle-filenames
969 (Bookmark-menu-toggle-filenames t))))))
970
971(defun Bookmark-menu-mark ()
972 "Mark bookmark on this line to be displayed by \\<Bookmark-menu-mode-map>\\[Bookmark-menu-select] command."
973 (interactive)
974 (beginning-of-line)
975 (if (Bookmark-menu-check-position)
976 (let ((buffer-read-only nil))
977 (delete-char 1)
978 (insert ?>)
979 (forward-line 1))))
980
981(defun Bookmark-menu-select ()
982 "Select this line's bookmark; also display bookmarks marked with `>'.
983You can mark bookmarks with the \\<Bookmark-menu-mode-map>\\[Bookmark-menu-mark] command."
984 (interactive)
985 (if (Bookmark-menu-check-position)
986 (let ((bmrk (Bookmark-menu-bookmark))
987 (menu (current-buffer))
988 (others ())
989 tem)
990 (goto-char (point-min))
991 (while (re-search-forward "^>" nil t)
992 (setq tem (Bookmark-menu-bookmark))
993 (let ((buffer-read-only nil))
994 (delete-char -1)
995 (insert ?\ ))
996 (or (string-equal tem bmrk)
997 (memq tem others)
998 (setq others (cons tem others))))
999 (setq others (nreverse others)
1000 tem (/ (1- (frame-height)) (1+ (length others))))
1001 (delete-other-windows)
1002 (bookmark-jump bmrk)
1003 (bury-buffer menu)
1004 (if (equal (length others) 0)
1005 nil
1006 (while others
1007 (split-window nil tem)
1008 (other-window 1)
1009 (bookmark-jump (car others))
1010 (setq others (cdr others)))
1011 (other-window 1)))))
1012
1013(defun Bookmark-menu-save (parg)
1014 "Save the current list into a bookmark file.
1015With a prefix arg, prompts for a file to save them in."
1016 (interactive "P")
1017 (save-excursion
1018 (save-window-excursion
1019 (bookmark-save parg))))
1020
1021(defun Bookmark-menu-load ()
1022 "Load a bookmark file and rebuild list."
1023 (interactive)
1024 (if (Bookmark-menu-check-position)
1025 (save-excursion
1026 (save-window-excursion
1027 (call-interactively 'bookmark-load)))))
1028
1029(defun Bookmark-menu-1-window ()
1030 "Select this line's bookmark, alone, in full frame."
1031 (interactive)
1032 (if (Bookmark-menu-check-position)
1033 (progn
1034 (bookmark-jump (Bookmark-menu-bookmark))
1035 (bury-buffer (other-buffer))
1036 (delete-other-windows))))
1037
1038(defun Bookmark-menu-2-window ()
1039 "Select this line's bookmark, with previous buffer in second window."
1040 (interactive)
1041 (if (Bookmark-menu-check-position)
1042 (let ((bmrk (Bookmark-menu-bookmark))
1043 (menu (current-buffer))
1044 (pop-up-windows t))
1045 (delete-other-windows)
1046 (switch-to-buffer (other-buffer))
1047 (let ((buff (car (bookmark-jump-noselect bmrk))))
1048 (pop-to-buffer buff))
1049 (bury-buffer menu))))
1050
1051(defun Bookmark-menu-this-window ()
1052 "Select this line's bookmark in this window."
1053 (interactive)
1054 (if (Bookmark-menu-check-position)
1055 (bookmark-jump (Bookmark-menu-bookmark))))
1056
1057(defun Bookmark-menu-other-window ()
1058 "Select this line's bookmark in other window, leaving bookmark menu visible."
1059 (interactive)
1060 (if (Bookmark-menu-check-position)
1061 (let ((buff (car (bookmark-jump-noselect (Bookmark-menu-bookmark)))))
1062 (switch-to-buffer-other-window buff))))
1063
1064(defun Bookmark-menu-switch-other-window ()
1065 "Make the other window select this line's bookmark.
1066The current window remains selected."
1067 (interactive)
1068 (if (Bookmark-menu-check-position)
1069 (let ((buff (car (bookmark-jump-noselect (Bookmark-menu-bookmark)))))
1070 (display-buffer buff))))
1071
1072(defun Bookmark-menu-quit ()
1073 "Quit the bookmark menu."
1074 (interactive)
1075 (let ((buffer (current-buffer)))
1076 (switch-to-buffer (other-buffer))
1077 (bury-buffer buffer)))
1078
1079(defun Bookmark-menu-unmark (&optional backup)
1080 "Cancel all requested operations on bookmark on this line and move down.
1081Optional ARG means move up."
1082 (interactive "P")
1083 (beginning-of-line)
1084 (if (Bookmark-menu-check-position)
1085 (progn
1086 (let ((buffer-read-only nil))
1087 (delete-char 1)
1088 ;; any flags to reset according to circumstances? How about a
1089 ;; flag indicating whether this bookmark is being visited?
1090 ;; well, we don't have this now, so maybe later.
1091 (insert " "))
1092 (forward-line (if backup -1 1)))))
1093
1094(defun Bookmark-menu-backup-unmark ()
1095 "Move up and cancel all requested operations on bookmark on line above."
1096 (interactive)
1097 (forward-line -1)
1098 (if (Bookmark-menu-check-position)
1099 (progn
1100 (Bookmark-menu-unmark)
1101 (forward-line -1))))
1102
1103(defun Bookmark-menu-delete ()
1104 "Mark bookmark on this line to be deleted by \\<Bookmark-menu-mode-map>\\[Bookmark-menu-execute] command."
1105 (interactive)
1106 (beginning-of-line)
1107 (if (Bookmark-menu-check-position)
1108 (let ((buffer-read-only nil))
1109 (delete-char 1)
1110 (insert ?D)
1111 (forward-line 1))))
1112
1113(defun Bookmark-menu-delete-backwards ()
1114 "Mark bookmark on this line to be deleted by \\<Bookmark-menu-mode-map>\\[Bookmark-menu-execute] command
1115and then move up one line"
1116 (interactive)
1117 (Bookmark-menu-delete)
1118 (forward-line -2)
1119 (if (Bookmark-menu-check-position)
1120 (forward-line 1)))
1121
1122(defun Bookmark-menu-execute ()
1123 "Delete bookmarks marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-delete] commands."
1124 (interactive)
1125 (let ((hide-em Bookmark-menu-toggle-filenames))
1126 (if hide-em (Bookmark-menu-hide-filenames))
1127 (setq Bookmark-menu-toggle-filenames nil)
1128 (goto-char (point-min))
1129 (forward-line 1)
1130 (let ((deaders ()))
1131 (while (re-search-forward "^D" (point-max) t)
1132 (setq deaders (cons (Bookmark-menu-bookmark) deaders)))
1133 (mapcar (lambda (str)
1134 (setq bookmark-alist
1135 (delq (assoc str bookmark-alist) bookmark-alist)))
1136 deaders))
1137 (list-bookmarks)
1138 (goto-char (point-min))
1139 (forward-line 2)
1140 (setq Bookmark-menu-toggle-filenames hide-em)
1141 (if Bookmark-menu-toggle-filenames
1142 (Bookmark-menu-toggle-filenames t))))
1143
1144(defun Bookmark-menu-rename ()
1145 "Rename bookmark on current line. Prompts for a new name."
1146 (interactive)
1147 (if (Bookmark-menu-check-position)
1148 (let ((bmrk (Bookmark-menu-bookmark))
1149 (thispoint (point)))
1150 (bookmark-rename bmrk)
1151 (list-bookmarks)
1152 (goto-char thispoint))))
1153
1154(defun Bookmark-menu-locate ()
1155 "Display location of this bookmark. Displays in the minibuffer."
1156 (interactive)
1157 (if (Bookmark-menu-check-position)
1158 (let ((bmrk (Bookmark-menu-bookmark)))
1159 (message (bookmark-locate bmrk t)))))
1160
11eb4275
RS
1161;;;; bookmark menu bar stuff ;;;;
1162
d22d6453 1163(defvar bookmark-menu-bar-length 70
9aef3b21 1164 "*Maximum length of a bookmark name displayed on a popup menu.")
b3bf02fa 1165
11eb4275 1166(defun bookmark-make-menu-bar-alist ()
d22d6453
RS
1167 (bookmark-try-default-file)
1168 (bookmark-maybe-sort-alist)
b3bf02fa
RS
1169 (if bookmark-alist
1170 (mapcar (lambda (cell)
1171 (let ((str (car cell)))
1172 (cons
11eb4275
RS
1173 (if (> (length str) bookmark-menu-bar-length)
1174 (substring str 0 bookmark-menu-bar-length)
b3bf02fa
RS
1175 str)
1176 str)))
1177 bookmark-alist)
1178 (error "No bookmarks currently set.")))
1179
11eb4275
RS
1180(defun bookmark-make-menu-bar-with-function (func-sym
1181 menu-label
1182 menu-str event)
b3bf02fa
RS
1183 ;; help function for making menus that need to apply a bookmark
1184 ;; function to a string.
11eb4275 1185 (let* ((menu (bookmark-make-menu-bar-alist))
b3bf02fa
RS
1186 (str (x-popup-menu event
1187 (list menu-label
d22d6453
RS
1188 (cons menu-str menu)))))
1189 (if str (apply func-sym (list str)))))
b3bf02fa 1190
11eb4275 1191(defun bookmark-menu-bar-insert (event)
9aef3b21
RS
1192 "Insert the text of the file pointed to by bookmark BOOKMARK.
1193You may have a problem using this function if the value of variable
1194`bookmark-alist' is nil. If that happens, you need to load in some
1195bookmarks. See help on function `bookmark-load' for more about
1196this."
b3bf02fa 1197 (interactive "e")
11eb4275 1198 (bookmark-make-menu-bar-with-function 'bookmark-insert
d22d6453
RS
1199 "Bookmark Insert Menu"
1200 "--- Insert Contents ---"
1201 event))
b3bf02fa 1202
11eb4275 1203(defun bookmark-menu-bar-jump (event)
9aef3b21
RS
1204 "Jump to bookmark BOOKMARK (a point in some file).
1205You may have a problem using this function if the value of variable
1206`bookmark-alist' is nil. If that happens, you need to load in some
1207bookmarks. See help on function `bookmark-load' for more about
1208this."
b3bf02fa 1209 (interactive "e")
11eb4275 1210 (bookmark-make-menu-bar-with-function 'bookmark-jump
d22d6453
RS
1211 "Bookmark Jump Menu"
1212 "--- Jump to Bookmark ---"
1213 event))
b3bf02fa 1214
11eb4275 1215(defun bookmark-menu-bar-locate (event)
9aef3b21
RS
1216 "Insert the name of the file associated with BOOKMARK.
1217\(This is not the same as the contents of that file\)."
b3bf02fa 1218 (interactive "e")
11eb4275 1219 (bookmark-make-menu-bar-with-function 'bookmark-locate
d22d6453
RS
1220 "Bookmark Locate Menu"
1221 "--- Insert Location ---"
1222 event))
b3bf02fa 1223
11eb4275 1224(defun bookmark-menu-bar-rename (event)
d22d6453
RS
1225 "Change the name of OLD-BOOKMARK to NEWNAME.
1226If called from keyboard, prompts for OLD-BOOKMARK and NEWNAME.
1227If called from menubar, OLD-BOOKMARK is selected from a menu, and
1228prompts for NEWNAME.
1229If called from Lisp, prompts for NEWNAME if only OLD-BOOKMARK was
1230passed as an argument. If called with two strings, then no prompting
1231is done. You must pass at least OLD-BOOKMARK when calling from Lisp.
9aef3b21
RS
1232
1233While you are entering the new name, consecutive C-w's insert
1234consectutive words from the text of the buffer into the new bookmark
1235name, and C-v inserts the name of the file."
b3bf02fa 1236 (interactive "e")
11eb4275 1237 (bookmark-make-menu-bar-with-function 'bookmark-rename
d22d6453
RS
1238 "Bookmark Rename Menu"
1239 "--- Rename Bookmark ---"
1240 event))
b3bf02fa 1241
11eb4275 1242(defun bookmark-menu-bar-delete (event)
9aef3b21
RS
1243 "Delete the bookmark named NAME from the bookmark list.
1244Removes only the first instance of a bookmark with that name. If
1245there are one or more other bookmarks with the same name, they will
1246not be deleted. Defaults to the \"current\" bookmark \(that is, the
1247one most recently used in this file, if any\)."
b3bf02fa 1248 (interactive "e")
11eb4275 1249 (bookmark-make-menu-bar-with-function 'bookmark-delete
d22d6453
RS
1250 "Bookmark Delete Menu"
1251 "--- Delete Bookmark ---"
1252 event))
b3bf02fa 1253
d22d6453
RS
1254;; Thanks to Roland McGrath for fixing menubar.el so that the
1255;; following works, and for explaining what to do to make it work.
b3bf02fa 1256
d22d6453 1257(defvar menu-bar-bookmark-map (make-sparse-keymap "Bookmark functions."))
b3bf02fa 1258
d22d6453
RS
1259;; make bookmarks appear toward the right side of the menu.
1260(if (boundp 'menu-bar-final-items)
1261 (if menu-bar-final-items
1262 (setq menu-bar-final-items
1263 (cons 'bookmark menu-bar-final-items)))
1264 (setq menu-bar-final-items '(bookmark)))
b3bf02fa 1265
d22d6453
RS
1266(define-key menu-bar-bookmark-map [load]
1267 '("Load a bookmark file" . bookmark-load))
b3bf02fa 1268
d22d6453
RS
1269(define-key menu-bar-bookmark-map [write]
1270 '("Write \(to another file\)" . bookmark-write))
1271
1272(define-key menu-bar-bookmark-map [save]
1273 '("Save \(in default file\)" . bookmark-save))
1274
1275(define-key menu-bar-bookmark-map [edit]
1276 '("Edit Bookmark List" . list-bookmarks))
1277
1278(define-key menu-bar-bookmark-map [delete]
1279 '("Delete bookmark" . bookmark-menu-bar-delete))
1280
1281(define-key menu-bar-bookmark-map [rename]
1282 '("Rename bookmark" . bookmark-menu-bar-rename))
1283
1284(define-key menu-bar-bookmark-map [locate]
1285 '("Insert location" . bookmark-menu-bar-locate))
b3bf02fa 1286
d22d6453
RS
1287(define-key menu-bar-bookmark-map [insert]
1288 '("Insert contents" . bookmark-menu-bar-insert))
1289
1290(define-key menu-bar-bookmark-map [set]
1291 '("Set bookmark" . bookmark-set))
1292
1293(define-key menu-bar-bookmark-map [jump]
1294 '("Jump to bookmark" . bookmark-menu-bar-jump))
1295
1296;;;###autoload (autoload 'menu-bar-bookmark-map "bookmark" nil t 'keymap)
1297
1298(fset 'menu-bar-bookmark-map (symbol-value 'menu-bar-bookmark-map))
1299
1300;;;; end bookmark menu-bar stuff ;;;;
b3bf02fa 1301
b3bf02fa
RS
1302(provide 'bookmark)
1303
11eb4275 1304;;; bookmark.el ends here