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