Mercurial > emacs
annotate lisp/bookmark.el @ 4679:ed9240986f40
(shell-dirstack-message): Recognize ~ by matching the expansion of "~" with
comint-filename-prefix prepended. Strip comint-filename-prefix from elts.
author | Roland McGrath <roland@gnu.org> |
---|---|
date | Wed, 08 Sep 1993 07:39:14 +0000 |
parents | cd8eef9ec0c4 |
children | 511c83aee4ae |
rev | line source |
---|---|
4537 | 1 ;;; bookmark.el --- set bookmarks, jump to them later. |
2 | |
3 ;; Copyright (C) 1993 Free Software Foundation, Inc. | |
4 | |
5 ;; Author: Karl Fogel <kfogel@cs.oberlin.edu> | |
4631 | 6 ;; Maintainer: Karl Fogel <kfogel@cs.oberlin.edu> |
4537 | 7 ;; Created: July, 1993 |
4595 | 8 ;; Version: 1.7.3 (interim) |
4537 | 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 | |
29 ;; sent *patches*, bless his soul... | |
30 | |
31 ;; Thanks to Gregory M. Saunders <saunders@cis.ohio-state.edu> for | |
32 ;; fixing and improving bookmark-time-to-save-p. | |
33 | |
34 ;; Based on info-bookmark.el, by Karl Fogel and Ken Olstad | |
35 ;; <olstad@msc.edu>. | |
36 | |
37 ;; LCD Archive Entry: | |
38 ;; bookmark|Karl Fogel|kfogel@cs.oberlin.edu| | |
39 ;; Setting bookmarks in files or directories, jumping to them later.| | |
40 ;; 16-July-93|Version: 1.7.2|~/misc/bookmark.el.Z| | |
41 | |
42 ;; FAVORITE CHINESE RESTAURANT: | |
43 ;; Boy, that's a tough one. Probably Hong Min, or maybe Emperor's | |
44 ;; Choice (both in Chicago's Chinatown). Well, both. How about you? | |
45 | |
46 ;;; Commentary on code: | |
47 | |
48 ;; bookmark alist format: | |
49 ;; (... | |
50 ;; (bookmark-name (filename | |
51 ;; string-in-front | |
52 ;; string-behind | |
53 ;; point)) | |
54 ;; ...) | |
55 ;; | |
56 ;; bookmark-name is the string the user gives the bookmark and | |
57 ;; accesses it by from then on. filename is the location of the file | |
58 ;; in which the bookmark is set. string-in-front is a string of | |
59 ;; `bookmark-search-size' chars of context in front of the point the | |
60 ;; bookmark is set at, string-behind is the same thing after the | |
61 ;; point. bookmark-jump will search for string-behind and | |
62 ;; string-in-front in case the file has changed since the bookmark was | |
63 ;; set. It will attempt to place the user before the changes, if | |
64 ;; there were any. | |
4595 | 65 ;; |
66 ;; It is not advisable to sort the bookmark list when it is presented | |
67 ;; to the user, because it is already sorted in what is probably the | |
68 ;; most useful way: order of creation, with most recently created | |
69 ;; bookmarks coming first and older ones toward the end (renaming does | |
70 ;; not count as creating) -- which is what we want, most of the time. | |
4537 | 71 |
72 ;;; Code: | |
73 | |
74 ;; Added for lucid emacs compatibility, db | |
75 (or (fboundp 'defalias) (fset 'defalias 'fset)) | |
76 | |
77 ;; these are the distribution keybindings suggested by RMS, everything | |
78 ;; else will be done with M-x or the menubar: | |
79 (define-key ctl-x-map "rb" 'bookmark-jump) | |
80 (define-key ctl-x-map "rm" 'bookmark-set) | |
81 (define-key ctl-x-map "rl" 'bookmark-locate) | |
82 | |
83 ;; define the map, so it can be bound by those who desire to do so: | |
84 | |
4633 | 85 (defvar bookmark-map nil |
86 "Keymap containing bindings to bookmark functions. | |
87 It is not bound to any key by default: to bind it | |
88 so that you have a bookmark prefix, just use `global-set-key' and bind a | |
89 key of your choice to `bookmark-map'. All interactive bookmark | |
4537 | 90 functions have a binding in this keymap.") |
91 | |
92 (define-prefix-command 'bookmark-map) | |
93 | |
94 ;; Read the help on all of these functions for details... | |
95 ;; "x" marks the spot! | |
96 (define-key bookmark-map "x" 'bookmark-set) | |
97 (define-key bookmark-map "j" 'bookmark-jump) | |
98 (define-key bookmark-map "i" 'bookmark-insert) | |
99 (define-key bookmark-map "f" 'bookmark-locate) ; "f" for "find" | |
4633 | 100 (define-key bookmark-map "r" 'bookmark-rename) |
4537 | 101 ;; deletes bookmarks |
102 (define-key bookmark-map "d" 'bookmark-delete) | |
103 ;; loads new file | |
104 (define-key bookmark-map "l" 'bookmark-load) | |
105 ;; saves them in file | |
106 (define-key bookmark-map "w" 'bookmark-write) | |
107 (define-key bookmark-map "s" 'bookmark-save) | |
108 | |
4634
cd8eef9ec0c4
(bookmark-alist): Move defvar before first use.
Richard M. Stallman <rms@gnu.org>
parents:
4633
diff
changeset
|
109 (defvar bookmark-alist () |
cd8eef9ec0c4
(bookmark-alist): Move defvar before first use.
Richard M. Stallman <rms@gnu.org>
parents:
4633
diff
changeset
|
110 "Association list of bookmarks. |
cd8eef9ec0c4
(bookmark-alist): Move defvar before first use.
Richard M. Stallman <rms@gnu.org>
parents:
4633
diff
changeset
|
111 You probably don't want to change the value of this alist yourself; |
cd8eef9ec0c4
(bookmark-alist): Move defvar before first use.
Richard M. Stallman <rms@gnu.org>
parents:
4633
diff
changeset
|
112 instead, let the various bookmark functions do it for you.") |
cd8eef9ec0c4
(bookmark-alist): Move defvar before first use.
Richard M. Stallman <rms@gnu.org>
parents:
4633
diff
changeset
|
113 |
4537 | 114 ;; just add the hook to make sure that people don't lose bookmarks |
115 ;; when they kill Emacs, unless they don't want to save them. | |
116 | |
117 (add-hook 'kill-emacs-hook | |
118 (function | |
119 (lambda () | |
120 (and (featurep 'bookmark) | |
121 bookmark-alist | |
122 (bookmark-time-to-save-p t) | |
123 (bookmark-save))))) | |
124 | |
125 ;; more stuff added by db. | |
126 (defvar bookmark-current-bookmark nil | |
4633 | 127 "Name of bookmark most recently used in the current file. |
128 It is buffer local, used to make moving a bookmark forward | |
4631 | 129 through a file easier.") |
4537 | 130 |
131 (make-variable-buffer-local 'bookmark-current-bookmark) | |
132 | |
133 (defvar bookmark-save-flag t | |
4633 | 134 "*Controls when Emacs saves bookmarks to a file. |
135 --> Nil means never save bookmarks, except when `bookmark-save' is | |
136 explicitly called \(\\[bookmark-save]\). | |
137 --> t means save bookmarks when Emacs is killed. | |
138 --> Otherise, it should be a number that is the frequency with which | |
139 the bookmark list is saved \(i.e.: the number of times which | |
140 Emacs' bookmark list may be modified before it is automatically | |
141 saved.\). If it is a number, Emacs will also automatically save | |
142 bookmarks when it is killed. | |
4537 | 143 |
144 Therefore, the way to get it to save every time you make or delete a | |
145 bookmark is to set this variable to 1 \(or 0, which produces the same | |
146 behavior.\) | |
147 | |
148 To specify the file in which to save them, modify the variable | |
4633 | 149 bookmark-file, which is `~/.emacs-bkmrks' by default.") |
4537 | 150 |
151 (defvar bookmark-alist-modification-count 0 | |
4633 | 152 "Number of modifications to bookmark list since it was last saved.") |
4537 | 153 |
154 (defvar bookmark-file "~/.emacs-bkmrks" | |
155 "*File in which to save bookmarks by default.") | |
156 | |
157 (defvar bookmark-completion-ignore-case t | |
4633 | 158 "*Non-nil means bookmark functions ignore case in completion.") |
4537 | 159 |
4633 | 160 (defvar bookmark-search-size 500 |
161 "Length of the context strings recorded on either side of a bookmark.") | |
4537 | 162 |
163 (defvar bookmark-current-point 0) | |
164 (defvar bookmark-yank-point 0) | |
165 (defvar bookmark-current-buffer nil) | |
166 | |
167 (defun bookmark-set (&optional parg) | |
4633 | 168 |
169 "Set a bookmark named NAME inside a file. | |
170 With prefix arg, will not overwrite a bookmark that has the same name | |
171 as NAME if such a bookmark already exists, but instead will \"push\" | |
172 the new bookmark onto the bookmark alist. Thus the most recently set | |
173 bookmark with name NAME would be the one in effect at any given time, | |
174 but the others are still there, should you decide to delete the most | |
175 recent one. | |
4537 | 176 |
177 To yank words from the text of the buffer and use them as part of the | |
4633 | 178 bookmark name, type C-w while setting a bookmark. Successive C-w's |
4537 | 179 yank successive words. |
180 | |
181 Typing C-v inserts the name of the current file being visited. Typing | |
182 C-u inserts the name of the last bookmark used in the buffer \(as an | |
183 aid in using a single bookmark name to track your progress through a | |
184 large file\). If no bookmark was used, then C-u behaves like C-v and | |
185 inserts the name of the file being visited. | |
186 | |
187 Use \\[bookmark-delete] to remove bookmarks \(you give it a name, | |
188 and it removes only the first instance of a bookmark with that name from | |
189 the list of bookmarks.\)" | |
190 (interactive "P") | |
191 (if (not (bookmark-buffer-file-name)) | |
192 (error "Buffer not visiting a file or directory.")) | |
193 (setq bookmark-current-point (point)) | |
194 (setq bookmark-yank-point (point)) | |
195 (setq bookmark-current-buffer (current-buffer)) | |
196 (let ((str | |
197 (read-from-minibuffer | |
198 "Set bookmark: " | |
199 nil | |
200 (let ((now-map (copy-keymap minibuffer-local-map))) | |
201 (progn (define-key now-map "\C-w" | |
202 'bookmark-yank-word) | |
203 (define-key now-map "\C-v" | |
204 'bookmark-insert-current-file-name) | |
205 (define-key now-map "\C-u" | |
206 'bookmark-insert-current-bookmark)) | |
207 now-map)))) | |
208 (progn | |
209 (bookmark-make parg str) | |
210 (setq bookmark-current-bookmark str) | |
211 (goto-char bookmark-current-point)))) | |
212 | |
213 (defun bookmark-insert-current-bookmark () | |
214 ;; insert this buffer's value of bookmark-current-bookmark, default | |
215 ;; to file name if it's nil. | |
216 (interactive) | |
217 (let ((str | |
218 (save-excursion | |
219 (set-buffer bookmark-current-buffer) | |
220 bookmark-current-bookmark))) | |
221 (if str (insert str) (bookmark-insert-current-file-name)))) | |
222 | |
223 (defun bookmark-insert-current-file-name () | |
224 ;; insert the name (sans path) of the current file into the bookmark | |
225 ;; name that is being set. | |
226 (interactive) | |
227 (let ((str (save-excursion | |
228 (set-buffer bookmark-current-buffer) | |
229 (bookmark-buffer-file-name)))) | |
230 (insert (substring | |
231 str | |
232 (1+ (string-match | |
233 "\\(/[^/]*\\)/*$" | |
234 str)))))) | |
235 | |
236 (defun bookmark-yank-word () | |
237 (interactive) | |
238 ;; get the next word from the buffer and append it to the name of | |
239 ;; the bookmark currently being set. | |
240 (let ((string (save-excursion | |
241 (set-buffer bookmark-current-buffer) | |
242 (goto-char bookmark-yank-point) | |
243 (buffer-substring | |
244 (point) | |
245 (save-excursion | |
246 (forward-word 1) | |
247 (setq bookmark-yank-point (point))))))) | |
248 (insert string))) | |
249 | |
250 (defun bookmark-make (parg str) | |
251 (if (and (assoc str bookmark-alist) (not parg)) | |
252 ;; already existing boookmark under that name and | |
253 ;; no prefix arg means just overwrite old bookmark | |
254 (setcdr (assoc str bookmark-alist) | |
255 (list (bookmark-make-cell))) | |
256 | |
257 ;; otherwise just cons it onto the front (either the bookmark | |
258 ;; doesn't exist already, or there is no prefix arg. In either | |
259 ;; case, we want the new bookmark consed onto the alist...) | |
260 | |
261 (setq bookmark-alist | |
262 (cons | |
263 (list str | |
264 (bookmark-make-cell)) | |
265 bookmark-alist))) | |
266 ;; Added by db | |
267 (setq bookmark-current-bookmark str) | |
268 (setq bookmark-alist-modification-count | |
269 (1+ bookmark-alist-modification-count)) | |
270 (if (bookmark-time-to-save-p) | |
271 (bookmark-save))) | |
272 | |
273 (defun bookmark-make-cell () | |
274 ;; make the cell that is the cdr of a bookmark alist element. It | |
275 ;; looks like this: | |
276 ;; (filename search-forward-str search-back-str point) | |
277 (list | |
278 (bookmark-buffer-file-name) | |
279 (if (>= (- (point-max) (point)) bookmark-search-size) | |
280 (buffer-substring | |
281 (point) | |
282 (+ (point) bookmark-search-size)) | |
283 nil) | |
284 (if (>= (- (point) (point-min)) bookmark-search-size) | |
285 (buffer-substring | |
286 (point) | |
287 (- (point) bookmark-search-size)) | |
288 nil) | |
289 (point))) | |
290 | |
291 (defun bookmark-buffer-file-name () | |
292 (or | |
293 buffer-file-name | |
294 (if (and (boundp 'dired-directory) dired-directory) | |
295 (if (stringp dired-directory) | |
296 dired-directory | |
297 (car dired-directory))))) | |
298 | |
299 (defun bookmark-try-default-file () | |
300 (if (and (null bookmark-alist) | |
301 (file-readable-p (expand-file-name bookmark-file))) | |
302 (bookmark-load bookmark-file))) | |
4631 | 303 |
4537 | 304 (defun bookmark-jump (str) |
4633 | 305 "Jump to bookmark BOOKMARK (a point in some file). |
306 You may have a problem using this function if the value of variable | |
307 `bookmark-alist' is nil. If that happens, you need to load in some | |
308 bookmarks. See help on function `bookmark-load' for more about | |
4631 | 309 this." |
4595 | 310 (interactive (let ((completion-ignore-case |
4537 | 311 bookmark-completion-ignore-case)) |
312 (list (completing-read | |
313 "Jump to bookmark: " | |
314 bookmark-alist | |
315 nil | |
4595 | 316 0)))) |
317 (let ((whereto-list (car (cdr (assoc str bookmark-alist))))) | |
318 (let ((file (car whereto-list)) | |
319 (forward-str (car (cdr whereto-list))) | |
320 (behind-str (car (cdr (cdr whereto-list)))) | |
321 (place (car (cdr (cdr (cdr whereto-list)))))) | |
322 (if (file-exists-p (expand-file-name file)) | |
323 (progn | |
324 (find-file (expand-file-name file)) | |
325 (goto-char place) | |
326 ;; Go searching forward first. Then, if forward-str exists and | |
327 ;; was found in the file, we can search backward for behind-str. | |
328 ;; Rationale is that if text was inserted between the two in the | |
329 ;; file, it's better to be put before it so you can read it, | |
330 ;; rather than after and remain perhaps unaware of the changes. | |
331 (if forward-str | |
332 (if (search-forward forward-str (point-max) t) | |
333 (backward-char bookmark-search-size))) | |
334 (if behind-str | |
335 (if (search-backward behind-str (point-min) t) | |
336 (forward-char bookmark-search-size))) | |
337 ;; added by db | |
338 (setq bookmark-current-bookmark str)) | |
339 (error | |
340 (concat "File " | |
341 file | |
342 " does not exist. Suggest deleting bookmark \"" | |
343 str | |
344 "\"")))))) | |
4537 | 345 |
346 (defun bookmark-locate (str) | |
4633 | 347 "Insert the name of the file associated with BOOKMARK. |
348 \(This is not the same as the contents of that file\)." | |
4595 | 349 (interactive (let ((completion-ignore-case |
350 bookmark-completion-ignore-case)) | |
351 (list (completing-read | |
352 "Insert bookmark location: " | |
353 bookmark-alist | |
354 nil | |
355 0)))) | |
4537 | 356 (insert (car (car (cdr (assoc str bookmark-alist)))))) |
357 | |
4633 | 358 (defun bookmark-rename (old &optional new) |
359 "Change the name of BOOKMARK to NEWNAME. | |
360 If called from keyboard, prompts for OLD and NEWNAME. | |
361 If called from menubar, prompts for NEWNAME. | |
362 If called from Lisp, prompts for NEWNAME if only BOOKMARK was passed | |
363 as an argument. If called with two strings, then no prompting is | |
364 done. You must pass at least BOOKMARK when calling from Lisp. | |
365 | |
366 While you are entering the new name, consecutive C-w's insert | |
367 consectutive words from the text of the buffer into the new bookmark | |
368 name, and C-v inserts the name of the file." | |
369 | |
4595 | 370 (interactive (let ((completion-ignore-case |
371 bookmark-completion-ignore-case)) | |
372 (list (completing-read "Old bookmark name: " | |
373 bookmark-alist | |
374 nil | |
375 0)))) | |
4537 | 376 (progn |
377 (setq bookmark-current-point (point)) | |
378 (setq bookmark-yank-point (point)) | |
379 (setq bookmark-current-buffer (current-buffer)) | |
380 (let ((cell (assoc old bookmark-alist)) | |
381 (str | |
4633 | 382 (or new ; use second arg, if non-nil |
383 (read-from-minibuffer | |
384 "New name: " | |
385 nil | |
386 (let ((now-map (copy-keymap minibuffer-local-map))) | |
387 (progn (define-key now-map "\C-w" | |
388 'bookmark-yank-word) | |
389 (define-key now-map "\C-v" | |
390 'bookmark-insert-current-file-name)) | |
391 now-map))))) | |
4537 | 392 (progn |
393 (setcar cell str) | |
394 (setq bookmark-current-bookmark str) | |
395 (setq bookmark-alist-modification-count | |
396 (1+ bookmark-alist-modification-count)) | |
397 (if (bookmark-time-to-save-p) | |
398 (bookmark-save)))))) | |
399 | |
400 (defun bookmark-insert (str) | |
4633 | 401 "Insert the text of the file pointed to by bookmark BOOKMARK. |
402 You may have a problem using this function if the value of variable | |
403 `bookmark-alist' is nil. If that happens, you need to load in some | |
404 bookmarks. See help on function `bookmark-load' for more about | |
4631 | 405 this." |
4595 | 406 (interactive (let ((completion-ignore-case |
407 bookmark-completion-ignore-case)) | |
408 (list (completing-read | |
409 "Insert bookmark contents: " | |
410 bookmark-alist | |
411 nil | |
412 0)))) | |
4537 | 413 (let ((whereto-list (car (cdr (assoc str bookmark-alist))))) |
414 (let ((file (car whereto-list))) | |
415 (if (file-readable-p (expand-file-name file)) | |
416 (let ((str-to-insert | |
417 (save-excursion | |
418 (find-file (expand-file-name file)) | |
419 (prog1 | |
420 (buffer-substring (point-min) (point-max)) | |
421 (bury-buffer)))) | |
422 (orig-point (point))) | |
423 (insert str-to-insert) | |
424 (push-mark) | |
425 (goto-char orig-point)) | |
426 (error | |
427 (concat "File " | |
428 file | |
429 " does not exist. Suggest deleting bookmark \"" | |
430 str | |
431 "\"")))))) | |
432 | |
433 (defun bookmark-delete (str) | |
4633 | 434 "Delete the bookmark named NAME from the bookmark list. |
435 Removes only the first instance of a bookmark with that name. If | |
436 there are one or more other bookmarks with the same name, they will | |
437 not be deleted. Defaults to the \"current\" bookmark \(that is, the | |
438 one most recently used in this file, if any\)." | |
439 | |
4537 | 440 (interactive (let ((completion-ignore-case |
441 bookmark-completion-ignore-case)) | |
442 (list | |
4595 | 443 (completing-read |
444 "Delete bookmark: " | |
445 bookmark-alist | |
446 nil | |
447 0 | |
448 bookmark-current-bookmark)))) | |
449 (let ((will-go (assoc str bookmark-alist))) | |
450 (setq bookmark-alist (delq will-go bookmark-alist)) | |
451 ;; Added by db, nil bookmark-current-bookmark if the last | |
452 ;; occurence has been deleted | |
4537 | 453 (or (assoc bookmark-current-bookmark bookmark-alist) |
4595 | 454 (setq bookmark-current-bookmark nil))) |
455 (setq bookmark-alist-modification-count | |
456 (1+ bookmark-alist-modification-count)) | |
457 (if (bookmark-time-to-save-p) | |
458 (bookmark-save))) | |
4537 | 459 |
460 (defun bookmark-time-to-save-p (&optional last-time) | |
461 ;; By Gregory M. Saunders <saunders@cis.ohio-state.edu> | |
462 ;; finds out whether it's time to save bookmarks to a file, by | |
463 ;; examining the value of variable bookmark-save-flag, and maybe | |
464 ;; bookmark-alist-modification-count. Returns t if they should be | |
465 ;; saved, nil otherwise. if last-time is non-nil, then this is | |
466 ;; being called when emacs is killed. | |
467 (cond (last-time | |
468 (and (> bookmark-alist-modification-count 0) | |
469 bookmark-save-flag)) | |
470 ((numberp bookmark-save-flag) | |
471 (>= bookmark-alist-modification-count bookmark-save-flag)) | |
472 (t | |
473 nil))) | |
474 | |
475 (defun bookmark-write () | |
476 (interactive) | |
477 (bookmark-save t)) | |
478 | |
4595 | 479 (defun bookmark-save (&optional parg file) |
4633 | 480 "Save currently defined bookmarks. |
481 Saves by default in the file defined by the variable | |
482 `bookmark-file'. With a prefix arg, save it in file FILE. | |
4537 | 483 |
484 If you are calling this from Lisp, the two arguments are PREFIX-ARG | |
485 and FILE, and if you just want it to write to the default file, then | |
486 pass no arguments. Or pass in nil and FILE, and it will save in FILE | |
487 instead. If you pass in one argument, and it is non-nil, then the | |
488 user will be interactively queried for a file to save in. | |
489 | |
4595 | 490 When you want to load in the bookmarks from a file, use |
4633 | 491 \`bookmark-load\', \\[bookmark-load]. That function will prompt you |
4595 | 492 for a file, defaulting to the file defined by variable |
4633 | 493 `bookmark-file'." |
4537 | 494 (interactive "P") |
495 (cond | |
496 ((and (null parg) (null file)) | |
497 ;;whether interactive or not, write to default file | |
498 (bookmark-write-file bookmark-file)) | |
499 ((and (null parg) file) | |
500 ;;whether interactive or not, write to given file | |
501 (bookmark-write-file file)) | |
502 ((and parg (not file)) | |
503 ;;have been called interactively w/ prefix arg | |
504 (let ((file (read-file-name "File to save bookmarks in: "))) | |
505 (bookmark-write-file file))) | |
506 (t ; someone called us with prefix-arg *and* a file, so just write to file | |
507 (bookmark-write-file file))) | |
508 ;; signal that we have synced the bookmark file by setting this to | |
509 ;; 0. If there was an error at any point before, it will not get | |
510 ;; set, which is what we want. | |
511 (setq bookmark-alist-modification-count 0)) | |
512 | |
513 (defun bookmark-write-file (file) | |
514 (save-excursion | |
515 (message (format "Saving bookmarks to file %s." file)) | |
516 (set-buffer (find-file-noselect file)) | |
517 (goto-char (point-min)) | |
518 (delete-region (point-min) (point-max)) | |
519 (print bookmark-alist (current-buffer)) | |
520 (write-file file) | |
521 (kill-buffer (current-buffer)))) | |
522 | |
523 (defun bookmark-load (file &optional revert no-msg) | |
4633 | 524 "Load bookmarks from FILE (which must be in bookmark format). |
525 Appends loaded bookmarks to the front of the list of bookmarks. If | |
526 optional second argument REVERT is non-nil, existing bookmarks are | |
527 destroyed. Optional third arg NO-MSG means don't display any messages | |
528 while loading. | |
4537 | 529 |
530 If you load a file that doesn't contain a proper bookmark alist, you | |
4633 | 531 will corrupt Emacs's bookmark list. Generally, you should only load |
4537 | 532 in files that were created with the bookmark functions in the first |
4633 | 533 place. Your own personal bookmark file, `~/.emacs-bkmrks', is |
4631 | 534 maintained automatically by Emacs; you shouldn't need to load it |
4595 | 535 explicitly." |
4537 | 536 (interactive |
537 (list (read-file-name | |
538 (format "Load bookmarks from: (%s) " | |
539 bookmark-file) | |
540 ;;Default might not be used often, | |
541 ;;but there's no better default, and | |
542 ;;I guess it's better than none at all. | |
543 "~/" bookmark-file 'confirm))) | |
544 (setq file (expand-file-name file)) | |
545 (if (file-readable-p file) | |
546 (save-excursion | |
547 (if (null no-msg) | |
548 (message (format "Loading bookmarks from %s..." file))) | |
549 (set-buffer (find-file-noselect file)) | |
550 (goto-char (point-min)) | |
551 (let ((blist (car (read-from-string | |
552 (buffer-substring (point-min) (point-max)))))) | |
553 (if (listp blist) | |
554 (progn | |
555 (if (not revert) | |
556 (setq bookmark-alist-modification-count | |
557 (1+ bookmark-alist-modification-count)) | |
558 (setq bookmark-alist-modification-count 0)) | |
559 (setq bookmark-alist | |
560 (append blist (if (not revert) bookmark-alist)))) | |
561 (error (format "Invalid bookmark list in %s." file)))) | |
562 (kill-buffer (current-buffer)) | |
563 (if (null no-msg) | |
564 (message (format "Loading bookmarks from %s... done" file)))) | |
565 (error (format "Cannot read bookmark file %s." file)))) | |
566 | |
4595 | 567 ;;;; bookmark menu bar stuff ;;;; |
4537 | 568 |
4633 | 569 (defvar bookmark-menu-bar-length 70 |
570 "*Maximum length of a bookmark name displayed on a popup menu.") | |
4595 | 571 |
572 (defvar bookmark-enable-menu-bar t | |
4633 | 573 "*Non-nil means put a bookmark menu on the menu bar. |
574 \(Assuming that you are running Emacs under a windowing system, such | |
575 as X.\)") | |
4537 | 576 |
4595 | 577 (defun bookmark-make-menu-bar-alist () |
4537 | 578 (if (not bookmark-alist) |
579 (if (file-readable-p bookmark-file) | |
580 (bookmark-load bookmark-file))) | |
581 (if bookmark-alist | |
582 (mapcar (lambda (cell) | |
583 (let ((str (car cell))) | |
584 (cons | |
4595 | 585 (if (> (length str) bookmark-menu-bar-length) |
586 (substring str 0 bookmark-menu-bar-length) | |
4537 | 587 str) |
588 str))) | |
589 bookmark-alist) | |
590 (error "No bookmarks currently set."))) | |
591 | |
4595 | 592 (defun bookmark-make-menu-bar-with-function (func-sym |
593 menu-label | |
594 menu-str event) | |
4537 | 595 ;; help function for making menus that need to apply a bookmark |
596 ;; function to a string. | |
4595 | 597 (let* ((menu (bookmark-make-menu-bar-alist)) |
4537 | 598 (str (x-popup-menu event |
599 (list menu-label | |
600 (cons menu-str | |
601 menu))))) | |
602 (if str | |
603 (apply func-sym (list str))))) | |
604 | |
4595 | 605 (defun bookmark-menu-bar-insert (event) |
4633 | 606 "Insert the text of the file pointed to by bookmark BOOKMARK. |
607 You may have a problem using this function if the value of variable | |
608 `bookmark-alist' is nil. If that happens, you need to load in some | |
609 bookmarks. See help on function `bookmark-load' for more about | |
610 this." | |
4537 | 611 (interactive "e") |
4595 | 612 (bookmark-make-menu-bar-with-function 'bookmark-insert |
4537 | 613 "Bookmark Insert Menu" |
614 "--- Insert Contents ---" | |
615 event)) | |
616 | |
4595 | 617 (defun bookmark-menu-bar-jump (event) |
4633 | 618 "Jump to bookmark BOOKMARK (a point in some file). |
619 You may have a problem using this function if the value of variable | |
620 `bookmark-alist' is nil. If that happens, you need to load in some | |
621 bookmarks. See help on function `bookmark-load' for more about | |
622 this." | |
4537 | 623 (interactive "e") |
4595 | 624 (bookmark-make-menu-bar-with-function 'bookmark-jump |
4537 | 625 "Bookmark Jump Menu" |
626 "--- Jump to Bookmark ---" | |
627 event)) | |
628 | |
4595 | 629 (defun bookmark-menu-bar-locate (event) |
4633 | 630 "Insert the name of the file associated with BOOKMARK. |
631 \(This is not the same as the contents of that file\)." | |
4537 | 632 (interactive "e") |
4595 | 633 (bookmark-make-menu-bar-with-function 'bookmark-locate |
4537 | 634 "Bookmark Locate Menu" |
635 "--- Insert Location ---" | |
636 event)) | |
637 | |
4595 | 638 (defun bookmark-menu-bar-rename (event) |
4633 | 639 "Change the name of BOOKMARK to NEWNAME. |
640 If called from keyboard, prompts for OLD and NEWNAME. | |
641 If called from menubar, prompts for NEWNAME. | |
642 If called from Lisp, prompts for NEWNAME if only BOOKMARK was passed | |
643 as an argument. If called with two strings, then no prompting is | |
644 done. You must pass at least BOOKMARK when calling from Lisp. | |
645 | |
646 While you are entering the new name, consecutive C-w's insert | |
647 consectutive words from the text of the buffer into the new bookmark | |
648 name, and C-v inserts the name of the file." | |
4537 | 649 (interactive "e") |
4595 | 650 (bookmark-make-menu-bar-with-function 'bookmark-rename |
4537 | 651 "Bookmark Rename Menu" |
652 "--- Rename Bookmark ---" | |
653 event)) | |
654 | |
4595 | 655 (defun bookmark-menu-bar-delete (event) |
4633 | 656 "Delete the bookmark named NAME from the bookmark list. |
657 Removes only the first instance of a bookmark with that name. If | |
658 there are one or more other bookmarks with the same name, they will | |
659 not be deleted. Defaults to the \"current\" bookmark \(that is, the | |
660 one most recently used in this file, if any\)." | |
4537 | 661 (interactive "e") |
4595 | 662 (bookmark-make-menu-bar-with-function 'bookmark-delete |
4537 | 663 "Bookmark Delete Menu" |
664 "--- Delete Bookmark ---" | |
665 event)) | |
666 | |
4595 | 667 (if (and bookmark-enable-menu-bar window-system) |
4537 | 668 (progn |
669 (defvar menu-bar-bookmark-map | |
670 (make-sparse-keymap "Bookmark functions")) | |
671 | |
672 ;; make bookmarks appear toward the right side of the menu. | |
673 (if (boundp 'menu-bar-final-items) | |
674 (if menu-bar-final-items | |
675 (setq menu-bar-final-items | |
676 (cons 'bookmark menu-bar-final-items))) | |
677 (setq menu-bar-final-items '(bookmark))) | |
678 | |
679 (define-key global-map [menu-bar bookmark] | |
680 (cons "Bookmarks" menu-bar-bookmark-map)) | |
681 | |
682 (define-key menu-bar-bookmark-map [load] | |
683 '(" Load a bookmark file" . bookmark-load)) | |
684 | |
685 (define-key menu-bar-bookmark-map [write] | |
686 '("Write \(to another file\)" . bookmark-write)) | |
687 | |
688 (define-key menu-bar-bookmark-map [save] | |
4595 | 689 '("Save \(in default file\)" . bookmark-save)) |
4537 | 690 |
691 (define-key menu-bar-bookmark-map [delete] | |
4595 | 692 '(" Delete a bookmark" . bookmark-menu-bar-delete)) |
4537 | 693 |
694 (define-key menu-bar-bookmark-map [rename] | |
4595 | 695 '(" Rename bookmark" . bookmark-menu-bar-rename)) |
4537 | 696 |
697 (define-key menu-bar-bookmark-map [locate] | |
4595 | 698 '(" Insert location" . bookmark-menu-bar-locate)) |
4537 | 699 |
700 (define-key menu-bar-bookmark-map [insert] | |
4595 | 701 '(" Insert contents" . bookmark-menu-bar-insert)) |
4537 | 702 |
703 (define-key menu-bar-bookmark-map [set] | |
704 '(" Set bookmark" . bookmark-set)) | |
705 | |
706 (define-key menu-bar-bookmark-map [jump] | |
4595 | 707 '(" Go to bookmark" . bookmark-menu-bar-jump)))) |
4537 | 708 |
709 ;; not using properties because they make the menu sluggish in coming | |
710 ;; up -- too many tests to make. Instead, choosing a useless menu | |
711 ;; item just gets you an error now (see | |
4595 | 712 ;; bookmark-make-menu-bar-with-function) |
4537 | 713 ;; |
4595 | 714 ;; (put 'bookmark-menu-bar-jump 'menu-enable |
4537 | 715 ;; '(or bookmark-alist |
716 ;; (and (file-readable-p bookmark-file) | |
717 ;; (progn (bookmark-load bookmark-file) | |
718 ;; bookmark-alist)))) | |
719 ;; | |
4595 | 720 ;; (put 'bookmark-menu-bar-insert 'menu-enable |
4537 | 721 ;; '(or bookmark-alist |
722 ;; (and (file-readable-p bookmark-file) | |
723 ;; (progn (bookmark-load bookmark-file) | |
724 ;; bookmark-alist)))) | |
725 ;; | |
4595 | 726 ;; (put 'bookmark-menu-bar-locate 'menu-enable |
4537 | 727 ;; '(or bookmark-alist |
728 ;; (and (file-readable-p bookmark-file) | |
729 ;; (progn (bookmark-load bookmark-file) | |
730 ;; bookmark-alist)))) | |
731 ;; | |
4595 | 732 ;; (put 'bookmark-menu-bar-rename 'menu-enable |
4537 | 733 ;; '(or bookmark-alist |
734 ;; (and (file-readable-p bookmark-file) | |
735 ;; (progn (bookmark-load bookmark-file) | |
736 ;; bookmark-alist)))) | |
737 ;; | |
4595 | 738 ;; (put 'bookmark-menu-bar-delete 'menu-enable |
4537 | 739 ;; '(or bookmark-alist |
740 ;; (and (file-readable-p bookmark-file) | |
741 ;; (progn (bookmark-load bookmark-file) | |
742 ;; bookmark-alist)))) | |
743 ;; | |
4595 | 744 ;; (put 'bookmark-menu-bar-save 'menu-enable |
4537 | 745 ;; '(or bookmark-alist |
746 ;; (and (file-readable-p bookmark-file) | |
747 ;; (progn (bookmark-load bookmark-file) | |
748 ;; bookmark-alist)))) | |
749 ;; | |
4595 | 750 ;; (put 'bookmark-menu-bar-write 'menu-enable |
4537 | 751 ;; '(or bookmark-alist |
752 ;; (and (file-readable-p bookmark-file) | |
753 ;; (progn (bookmark-load bookmark-file) | |
754 ;; bookmark-alist)))) | |
755 | |
4595 | 756 ;;;; end bookmark menu-bar stuff ;;;; |
4537 | 757 |
758 ;; load the default bookmark file, if it exists, and the | |
759 ;; bookmark-alist is nil: | |
760 (bookmark-try-default-file) | |
761 | |
762 (provide 'bookmark) | |
763 | |
4595 | 764 ;;; bookmark.el ends here |