mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-24 07:20:37 +00:00
entered into RCS
This commit is contained in:
parent
3f469c2e5e
commit
b3bf02fa61
776
lisp/bookmark.el
Normal file
776
lisp/bookmark.el
Normal file
@ -0,0 +1,776 @@
|
||||
;;; bookmark.el --- set bookmarks, jump to them later.
|
||||
|
||||
;; Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Karl Fogel <kfogel@cs.oberlin.edu>
|
||||
;; Maintainer: FSF
|
||||
;; Created: July, 1993
|
||||
;; Version: 1.7.2
|
||||
;; Keywords: bookmarks, placeholders
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
;; Thanks to David Bremner <bremner@cs.sfu.ca> for thinking of and
|
||||
;; then implementing the bookmark-current-bookmark idea. He even
|
||||
;; sent *patches*, bless his soul...
|
||||
|
||||
;; Thanks to Gregory M. Saunders <saunders@cis.ohio-state.edu> for
|
||||
;; fixing and improving bookmark-time-to-save-p.
|
||||
|
||||
;; Based on info-bookmark.el, by Karl Fogel and Ken Olstad
|
||||
;; <olstad@msc.edu>.
|
||||
|
||||
;; LCD Archive Entry:
|
||||
;; bookmark|Karl Fogel|kfogel@cs.oberlin.edu|
|
||||
;; Setting bookmarks in files or directories, jumping to them later.|
|
||||
;; 16-July-93|Version: 1.7.2|~/misc/bookmark.el.Z|
|
||||
|
||||
;; FAVORITE CHINESE RESTAURANT:
|
||||
;; Boy, that's a tough one. Probably Hong Min, or maybe Emperor's
|
||||
;; Choice (both in Chicago's Chinatown). Well, both. How about you?
|
||||
|
||||
;;; Commentary on code:
|
||||
|
||||
;; bookmark alist format:
|
||||
;; (...
|
||||
;; (bookmark-name (filename
|
||||
;; string-in-front
|
||||
;; string-behind
|
||||
;; point))
|
||||
;; ...)
|
||||
;;
|
||||
;; bookmark-name is the string the user gives the bookmark and
|
||||
;; accesses it by from then on. filename is the location of the file
|
||||
;; in which the bookmark is set. string-in-front is a string of
|
||||
;; `bookmark-search-size' chars of context in front of the point the
|
||||
;; bookmark is set at, string-behind is the same thing after the
|
||||
;; point. bookmark-jump will search for string-behind and
|
||||
;; string-in-front in case the file has changed since the bookmark was
|
||||
;; set. It will attempt to place the user before the changes, if
|
||||
;; there were any.
|
||||
|
||||
;;; Code:
|
||||
|
||||
;; Added for lucid emacs compatibility, db
|
||||
(or (fboundp 'defalias) (fset 'defalias 'fset))
|
||||
|
||||
;; these are the distribution keybindings suggested by RMS, everything
|
||||
;; else will be done with M-x or the menubar:
|
||||
(define-key ctl-x-map "rb" 'bookmark-jump)
|
||||
(define-key ctl-x-map "rm" 'bookmark-set)
|
||||
(define-key ctl-x-map "rl" 'bookmark-locate)
|
||||
|
||||
;; define the map, so it can be bound by those who desire to do so:
|
||||
|
||||
(defvar bookmark-map nil "This is a keymap containing bookmark
|
||||
functions. It is not bound to any key by default: to bind it so
|
||||
that you have a bookmark prefix, just use global-set-key and bind a
|
||||
key of your choice to \'bookmark-map. All interactive bookmark
|
||||
functions have a binding in this keymap.")
|
||||
|
||||
(define-prefix-command 'bookmark-map)
|
||||
|
||||
;; Read the help on all of these functions for details...
|
||||
;; "x" marks the spot!
|
||||
(define-key bookmark-map "x" 'bookmark-set)
|
||||
(define-key bookmark-map "j" 'bookmark-jump)
|
||||
(define-key bookmark-map "i" 'bookmark-insert)
|
||||
(define-key bookmark-map "f" 'bookmark-locate) ; "f" for "find"
|
||||
(define-key bookmark-map "n" 'bookmark-rename) ; "n" for "new name"
|
||||
;; deletes bookmarks
|
||||
(define-key bookmark-map "d" 'bookmark-delete)
|
||||
;; loads new file
|
||||
(define-key bookmark-map "l" 'bookmark-load)
|
||||
;; saves them in file
|
||||
(define-key bookmark-map "w" 'bookmark-write)
|
||||
(define-key bookmark-map "s" 'bookmark-save)
|
||||
|
||||
;; just add the hook to make sure that people don't lose bookmarks
|
||||
;; when they kill Emacs, unless they don't want to save them.
|
||||
|
||||
(add-hook 'kill-emacs-hook
|
||||
(function
|
||||
(lambda ()
|
||||
(and (featurep 'bookmark)
|
||||
bookmark-alist
|
||||
(bookmark-time-to-save-p t)
|
||||
(bookmark-save)))))
|
||||
|
||||
;; more stuff added by db.
|
||||
(defvar bookmark-current-bookmark nil
|
||||
"Store the bookmark most recently set, jumped to, or renamed.
|
||||
Buffer local, used to make moving a bookmark forward through a
|
||||
file easier.")
|
||||
|
||||
(make-variable-buffer-local 'bookmark-current-bookmark)
|
||||
|
||||
(defvar bookmark-save-flag t
|
||||
"*Nil means never save bookmarks, except when bookmark-save is
|
||||
explicitly called \(\\[bookmark-save]\).
|
||||
|
||||
t means save bookmarks when Emacs is killed.
|
||||
|
||||
Otherise, it should be a number that is the frequency with which the
|
||||
bookmark list is saved \(i.e.: the number of times which Emacs\'
|
||||
bookmark list may be modified before it is automatically saved.\). If
|
||||
it is a number, Emacs will also automatically save bookmarks when it
|
||||
is killed.
|
||||
|
||||
Therefore, the way to get it to save every time you make or delete a
|
||||
bookmark is to set this variable to 1 \(or 0, which produces the same
|
||||
behavior.\)
|
||||
|
||||
To specify the file in which to save them, modify the variable
|
||||
bookmark-file, which is \"~/.emacs-bkmrks\" by default.")
|
||||
|
||||
(defvar bookmark-alist-modification-count 0
|
||||
"Number of times the bookmark list has been modified since last
|
||||
saved.")
|
||||
|
||||
(defvar bookmark-file "~/.emacs-bkmrks"
|
||||
"*File in which to save bookmarks by default.")
|
||||
|
||||
(defvar bookmark-completion-ignore-case t
|
||||
"*Non-nil means that the various bookmark functions that
|
||||
do completion will be case-insensitive in completion.")
|
||||
|
||||
(defvar bookmark-search-size 500 "Number of chars resolution used
|
||||
in creating tag strings to record a bookmark. Bookmark functions will
|
||||
search for these strings in deciding where to jump to, to deal with
|
||||
changing values of point. I can\'t think of any reason you would want
|
||||
to modify this, and doing so might have side effects, so on your own
|
||||
head be it...")
|
||||
|
||||
(defvar bookmark-alist ()
|
||||
"Association list of bookmarks.
|
||||
You probably don't want to change the value of this alist yourself;
|
||||
instead, let the various bookmark functions do it for you.")
|
||||
|
||||
(defvar bookmark-current-point 0)
|
||||
(defvar bookmark-yank-point 0)
|
||||
(defvar bookmark-current-buffer nil)
|
||||
|
||||
(defun bookmark-set (&optional parg)
|
||||
"Set a bookmark named NAME inside a file. With prefix arg, will not
|
||||
overwrite a bookmark that has the same name as NAME if such a bookmark
|
||||
already exists, but instead will \"push\" the new bookmark onto the
|
||||
bookmark alist. Thus the most recently set bookmark with name NAME would
|
||||
be the one in effect at any given time, but the others are still there,
|
||||
should you decide to delete the most recent one.
|
||||
|
||||
To yank words from the text of the buffer and use them as part of the
|
||||
bookmark name, type C-w while setting a bookmark. Successive C-w\'s
|
||||
yank successive words.
|
||||
|
||||
Typing C-v inserts the name of the current file being visited. Typing
|
||||
C-u inserts the name of the last bookmark used in the buffer \(as an
|
||||
aid in using a single bookmark name to track your progress through a
|
||||
large file\). If no bookmark was used, then C-u behaves like C-v and
|
||||
inserts the name of the file being visited.
|
||||
|
||||
Use \\[bookmark-delete] to remove bookmarks \(you give it a name,
|
||||
and it removes only the first instance of a bookmark with that name from
|
||||
the list of bookmarks.\)"
|
||||
(interactive "P")
|
||||
(if (not (bookmark-buffer-file-name))
|
||||
(error "Buffer not visiting a file or directory."))
|
||||
(setq bookmark-current-point (point))
|
||||
(setq bookmark-yank-point (point))
|
||||
(setq bookmark-current-buffer (current-buffer))
|
||||
(let ((str
|
||||
(read-from-minibuffer
|
||||
"Set bookmark: "
|
||||
nil
|
||||
(let ((now-map (copy-keymap minibuffer-local-map)))
|
||||
(progn (define-key now-map "\C-w"
|
||||
'bookmark-yank-word)
|
||||
(define-key now-map "\C-v"
|
||||
'bookmark-insert-current-file-name)
|
||||
(define-key now-map "\C-u"
|
||||
'bookmark-insert-current-bookmark))
|
||||
now-map))))
|
||||
(progn
|
||||
(bookmark-make parg str)
|
||||
(setq bookmark-current-bookmark str)
|
||||
(goto-char bookmark-current-point))))
|
||||
|
||||
(defun bookmark-insert-current-bookmark ()
|
||||
;; insert this buffer's value of bookmark-current-bookmark, default
|
||||
;; to file name if it's nil.
|
||||
(interactive)
|
||||
(let ((str
|
||||
(save-excursion
|
||||
(set-buffer bookmark-current-buffer)
|
||||
bookmark-current-bookmark)))
|
||||
(if str (insert str) (bookmark-insert-current-file-name))))
|
||||
|
||||
(defun bookmark-insert-current-file-name ()
|
||||
;; insert the name (sans path) of the current file into the bookmark
|
||||
;; name that is being set.
|
||||
(interactive)
|
||||
(let ((str (save-excursion
|
||||
(set-buffer bookmark-current-buffer)
|
||||
(bookmark-buffer-file-name))))
|
||||
(insert (substring
|
||||
str
|
||||
(1+ (string-match
|
||||
"\\(/[^/]*\\)/*$"
|
||||
str))))))
|
||||
|
||||
(defun bookmark-yank-word ()
|
||||
(interactive)
|
||||
;; get the next word from the buffer and append it to the name of
|
||||
;; the bookmark currently being set.
|
||||
(let ((string (save-excursion
|
||||
(set-buffer bookmark-current-buffer)
|
||||
(goto-char bookmark-yank-point)
|
||||
(buffer-substring
|
||||
(point)
|
||||
(save-excursion
|
||||
(forward-word 1)
|
||||
(setq bookmark-yank-point (point)))))))
|
||||
(insert string)))
|
||||
|
||||
(defun bookmark-make (parg str)
|
||||
(if (and (assoc str bookmark-alist) (not parg))
|
||||
;; already existing boookmark under that name and
|
||||
;; no prefix arg means just overwrite old bookmark
|
||||
(setcdr (assoc str bookmark-alist)
|
||||
(list (bookmark-make-cell)))
|
||||
|
||||
;; otherwise just cons it onto the front (either the bookmark
|
||||
;; doesn't exist already, or there is no prefix arg. In either
|
||||
;; case, we want the new bookmark consed onto the alist...)
|
||||
|
||||
(setq bookmark-alist
|
||||
(cons
|
||||
(list str
|
||||
(bookmark-make-cell))
|
||||
bookmark-alist)))
|
||||
;; Added by db
|
||||
(setq bookmark-current-bookmark str)
|
||||
(setq bookmark-alist-modification-count
|
||||
(1+ bookmark-alist-modification-count))
|
||||
(if (bookmark-time-to-save-p)
|
||||
(bookmark-save)))
|
||||
|
||||
(defun bookmark-make-cell ()
|
||||
;; make the cell that is the cdr of a bookmark alist element. It
|
||||
;; looks like this:
|
||||
;; (filename search-forward-str search-back-str point)
|
||||
(list
|
||||
(bookmark-buffer-file-name)
|
||||
(if (>= (- (point-max) (point)) bookmark-search-size)
|
||||
(buffer-substring
|
||||
(point)
|
||||
(+ (point) bookmark-search-size))
|
||||
nil)
|
||||
(if (>= (- (point) (point-min)) bookmark-search-size)
|
||||
(buffer-substring
|
||||
(point)
|
||||
(- (point) bookmark-search-size))
|
||||
nil)
|
||||
(point)))
|
||||
|
||||
(defun bookmark-buffer-file-name ()
|
||||
(or
|
||||
buffer-file-name
|
||||
(if (and (boundp 'dired-directory) dired-directory)
|
||||
(if (stringp dired-directory)
|
||||
dired-directory
|
||||
(car dired-directory)))))
|
||||
|
||||
(defun bookmark-try-default-file ()
|
||||
(if (and (null bookmark-alist)
|
||||
(file-readable-p (expand-file-name bookmark-file)))
|
||||
(bookmark-load bookmark-file)))
|
||||
|
||||
(defun bookmark-jump (str)
|
||||
"Go to the location saved in the bookmark BOOKMARK. You may have a
|
||||
problem using this function if the value of variable bookmark-alist
|
||||
is nil. If that happens, you need to load in some bookmarks. See
|
||||
help on function bookmark-load for more about this."
|
||||
(interactive (progn
|
||||
(bookmark-try-default-file)
|
||||
(let ((completion-ignore-case
|
||||
bookmark-completion-ignore-case))
|
||||
(list (completing-read
|
||||
"Jump to bookmark: "
|
||||
bookmark-alist
|
||||
nil
|
||||
0)))))
|
||||
(let ((whereto-list (car (cdr (assoc str bookmark-alist)))))
|
||||
(let ((file (car whereto-list))
|
||||
(forward-str (car (cdr whereto-list)))
|
||||
(behind-str (car (cdr (cdr whereto-list))))
|
||||
(place (car (cdr (cdr (cdr whereto-list))))))
|
||||
(if (file-exists-p (expand-file-name file))
|
||||
(progn
|
||||
(find-file (expand-file-name file))
|
||||
(goto-char place)
|
||||
;; Go searching forward first. Then, if forward-str exists and
|
||||
;; was found in the file, we can search backward for behind-str.
|
||||
;; Rationale is that if text was inserted between the two in the
|
||||
;; file, it's better to be put before it so you can read it,
|
||||
;; rather than after and remain perhaps unaware of the changes.
|
||||
(if forward-str
|
||||
(if (search-forward forward-str (point-max) t)
|
||||
(backward-char bookmark-search-size)))
|
||||
(if behind-str
|
||||
(if (search-backward behind-str (point-min) t)
|
||||
(forward-char bookmark-search-size)))
|
||||
;; added by db
|
||||
(setq bookmark-current-bookmark str))
|
||||
(error
|
||||
(concat "File "
|
||||
file
|
||||
" does not exist. Suggest deleting bookmark \""
|
||||
str
|
||||
"\""))))))
|
||||
|
||||
(defun bookmark-locate (str)
|
||||
"Insert the name of the file associated with BOOKMARK \(as opposed
|
||||
to the contents of that file\)."
|
||||
(interactive (progn
|
||||
(bookmark-try-default-file)
|
||||
(let ((completion-ignore-case
|
||||
bookmark-completion-ignore-case))
|
||||
(list (completing-read
|
||||
"Insert bookmark location: "
|
||||
bookmark-alist
|
||||
nil
|
||||
0)))))
|
||||
(insert (car (car (cdr (assoc str bookmark-alist))))))
|
||||
|
||||
(defun bookmark-rename (old)
|
||||
"Change the name of BOOKMARK to NEWNAME. While you are entering
|
||||
the new name, consecutive C-w\'s will insert consectutive words from
|
||||
the text of the buffer into the new bookmark name, and C-v will insert
|
||||
the name of the file."
|
||||
(interactive (progn
|
||||
(bookmark-try-default-file)
|
||||
(let ((completion-ignore-case
|
||||
bookmark-completion-ignore-case))
|
||||
(list (completing-read "Old bookmark name: "
|
||||
bookmark-alist
|
||||
nil
|
||||
0)))))
|
||||
(progn
|
||||
(setq bookmark-current-point (point))
|
||||
(setq bookmark-yank-point (point))
|
||||
(setq bookmark-current-buffer (current-buffer))
|
||||
(let ((cell (assoc old bookmark-alist))
|
||||
(str
|
||||
(read-from-minibuffer
|
||||
"New name: "
|
||||
nil
|
||||
(let ((now-map (copy-keymap minibuffer-local-map)))
|
||||
(progn (define-key now-map "\C-w"
|
||||
'bookmark-yank-word)
|
||||
(define-key now-map "\C-v"
|
||||
'bookmark-insert-current-file-name))
|
||||
now-map))))
|
||||
(progn
|
||||
(setcar cell str)
|
||||
(setq bookmark-current-bookmark str)
|
||||
(setq bookmark-alist-modification-count
|
||||
(1+ bookmark-alist-modification-count))
|
||||
(if (bookmark-time-to-save-p)
|
||||
(bookmark-save))))))
|
||||
|
||||
(defun bookmark-insert (str)
|
||||
"Insert the text of the file pointed to by bookmark BOOKMARK. You
|
||||
may have a problem using this function if the value of variable
|
||||
bookmark-alist is nil. If that happens, you need to load in some
|
||||
bookmarks. See help on function bookmark-load for more about this."
|
||||
(interactive (progn
|
||||
(bookmark-try-default-file)
|
||||
(let ((completion-ignore-case
|
||||
bookmark-completion-ignore-case))
|
||||
(list (completing-read
|
||||
"Insert bookmark contents: "
|
||||
bookmark-alist
|
||||
nil
|
||||
0)))))
|
||||
(let ((whereto-list (car (cdr (assoc str bookmark-alist)))))
|
||||
(let ((file (car whereto-list)))
|
||||
(if (file-readable-p (expand-file-name file))
|
||||
(let ((str-to-insert
|
||||
(save-excursion
|
||||
(find-file (expand-file-name file))
|
||||
(prog1
|
||||
(buffer-substring (point-min) (point-max))
|
||||
(bury-buffer))))
|
||||
(orig-point (point)))
|
||||
(insert str-to-insert)
|
||||
(push-mark)
|
||||
(goto-char orig-point))
|
||||
(error
|
||||
(concat "File "
|
||||
file
|
||||
" does not exist. Suggest deleting bookmark \""
|
||||
str
|
||||
"\""))))))
|
||||
|
||||
(defun bookmark-delete (str)
|
||||
"Delete the bookmark named NAME from the bookmark list. Removes
|
||||
only the first instance of a bookmark with that name. If there is
|
||||
another bookmark with the same name, it will become \"current\" as
|
||||
soon as the old one is removed from the bookmark list. Defaults to
|
||||
the \"current\" bookmark \(that is, the one most recently set or
|
||||
jumped to in this file\).
|
||||
|
||||
With a prefix argument, deletes all bookmarks \(will prompt for
|
||||
confirmation before such a drastic step, however.\) If you then save
|
||||
the empty bookmark list, they will truly be deleted; otherwise you
|
||||
will revert to the bookmarks saved in the default bookmark file
|
||||
automatically the next time you jump to a bookmark, insert one, rename
|
||||
one, or kill Emacs."
|
||||
(interactive (let ((completion-ignore-case
|
||||
bookmark-completion-ignore-case))
|
||||
(list
|
||||
(if current-prefix-arg
|
||||
nil
|
||||
(completing-read
|
||||
"Delete bookmark: "
|
||||
bookmark-alist
|
||||
nil
|
||||
0
|
||||
bookmark-current-bookmark)))))
|
||||
(if (null str)
|
||||
(if (y-or-n-p "Delete all bookmarks? ")
|
||||
(progn
|
||||
(setq bookmark-alist nil)
|
||||
(message
|
||||
(if (file-readable-p (expand-file-name bookmark-file))
|
||||
(format
|
||||
"Will revert to bookmarks in %s, unless you save now."
|
||||
bookmark-file)
|
||||
"All bookmarks deleted.")))
|
||||
(message "No bookmarks deleted."))
|
||||
(let ((will-go (assoc str bookmark-alist)))
|
||||
(setq bookmark-alist (delq will-go bookmark-alist)))
|
||||
;; Added by db, nil bookmark-current-bookmark if the last
|
||||
;; occurence has been deleted
|
||||
(or (assoc bookmark-current-bookmark bookmark-alist)
|
||||
(setq bookmark-current-bookmark nil)))
|
||||
(setq bookmark-alist-modification-count
|
||||
(1+ bookmark-alist-modification-count))
|
||||
(if (bookmark-time-to-save-p)
|
||||
(bookmark-save)))
|
||||
|
||||
(defun bookmark-time-to-save-p (&optional last-time)
|
||||
;; By Gregory M. Saunders <saunders@cis.ohio-state.edu>
|
||||
;; finds out whether it's time to save bookmarks to a file, by
|
||||
;; examining the value of variable bookmark-save-flag, and maybe
|
||||
;; bookmark-alist-modification-count. Returns t if they should be
|
||||
;; saved, nil otherwise. if last-time is non-nil, then this is
|
||||
;; being called when emacs is killed.
|
||||
(cond (last-time
|
||||
(and (> bookmark-alist-modification-count 0)
|
||||
bookmark-save-flag))
|
||||
((numberp bookmark-save-flag)
|
||||
(>= bookmark-alist-modification-count bookmark-save-flag))
|
||||
(t
|
||||
nil)))
|
||||
|
||||
(defun bookmark-write ()
|
||||
(interactive)
|
||||
(bookmark-save t))
|
||||
|
||||
(defun bookmark-save (&optional parg file)
|
||||
"Saves currently defined bookmarks in the file defined by
|
||||
the variable bookmark-file. With a prefix arg, save it in file
|
||||
FILE.
|
||||
|
||||
If you are calling this from Lisp, the two arguments are PREFIX-ARG
|
||||
and FILE, and if you just want it to write to the default file, then
|
||||
pass no arguments. Or pass in nil and FILE, and it will save in FILE
|
||||
instead. If you pass in one argument, and it is non-nil, then the
|
||||
user will be interactively queried for a file to save in.
|
||||
|
||||
When you want to load in the bookmarks from a file, use bookmark-load,
|
||||
\\[bookmark-load]. That function will prompt you for a file,
|
||||
defaulting to the file defined by variable bookmark-file."
|
||||
(interactive "P")
|
||||
(cond
|
||||
((and (null parg) (null file))
|
||||
;;whether interactive or not, write to default file
|
||||
(bookmark-write-file bookmark-file))
|
||||
((and (null parg) file)
|
||||
;;whether interactive or not, write to given file
|
||||
(bookmark-write-file file))
|
||||
((and parg (not file))
|
||||
;;have been called interactively w/ prefix arg
|
||||
(let ((file (read-file-name "File to save bookmarks in: ")))
|
||||
(bookmark-write-file file)))
|
||||
(t ; someone called us with prefix-arg *and* a file, so just write to file
|
||||
(bookmark-write-file file)))
|
||||
;; signal that we have synced the bookmark file by setting this to
|
||||
;; 0. If there was an error at any point before, it will not get
|
||||
;; set, which is what we want.
|
||||
(setq bookmark-alist-modification-count 0))
|
||||
|
||||
(defun bookmark-write-file (file)
|
||||
(save-excursion
|
||||
(message (format "Saving bookmarks to file %s." file))
|
||||
(set-buffer (find-file-noselect file))
|
||||
(goto-char (point-min))
|
||||
(delete-region (point-min) (point-max))
|
||||
(print bookmark-alist (current-buffer))
|
||||
(write-file file)
|
||||
(kill-buffer (current-buffer))))
|
||||
|
||||
(defun bookmark-load (file &optional revert no-msg)
|
||||
"Loads bookmarks from FILE, appending loaded bookmarks to the front
|
||||
of the list of bookmarks. If optional second argument REVERT is
|
||||
non-nil, existing bookmarks are destroyed. Optional third arg NO-MSG
|
||||
means don't display any messages while loading.
|
||||
|
||||
If you load a file that doesn't contain a proper bookmark alist, you
|
||||
will corrupt Emacs\' bookmark list. Generally, you should only load
|
||||
in files that were created with the bookmark functions in the first
|
||||
place. If the bookmark alist does become corrupted, just delete all
|
||||
bookmarks and your master bookmark-file will be automatically loaded
|
||||
next time you try to go to a bookmark \(assuming that your bookmark
|
||||
file itself is not corrupt, this will solve the problem\)."
|
||||
(interactive
|
||||
(list (read-file-name
|
||||
(format "Load bookmarks from: (%s) "
|
||||
bookmark-file)
|
||||
;;Default might not be used often,
|
||||
;;but there's no better default, and
|
||||
;;I guess it's better than none at all.
|
||||
"~/" bookmark-file 'confirm)))
|
||||
(setq file (expand-file-name file))
|
||||
(if (file-readable-p file)
|
||||
(save-excursion
|
||||
(if (null no-msg)
|
||||
(message (format "Loading bookmarks from %s..." file)))
|
||||
(set-buffer (find-file-noselect file))
|
||||
(goto-char (point-min))
|
||||
(let ((blist (car (read-from-string
|
||||
(buffer-substring (point-min) (point-max))))))
|
||||
(if (listp blist)
|
||||
(progn
|
||||
(if (not revert)
|
||||
(setq bookmark-alist-modification-count
|
||||
(1+ bookmark-alist-modification-count))
|
||||
(setq bookmark-alist-modification-count 0))
|
||||
(setq bookmark-alist
|
||||
(append blist (if (not revert) bookmark-alist))))
|
||||
(error (format "Invalid bookmark list in %s." file))))
|
||||
(kill-buffer (current-buffer))
|
||||
(if (null no-msg)
|
||||
(message (format "Loading bookmarks from %s... done" file))))
|
||||
(error (format "Cannot read bookmark file %s." file))))
|
||||
|
||||
;;;; bookmark menu stuff ;;;;
|
||||
|
||||
(defvar bookmark-enable-menus t
|
||||
"*Non-nil means put a bookmark menu on the menu bar \(assuming that
|
||||
you are running Emacs under a windowing system, such as X\).")
|
||||
|
||||
(defvar bookmark-menu-length 70 "*Maximum length of a bookmark name
|
||||
displayed on a menu.")
|
||||
|
||||
(defun bookmark-make-menu-alist ()
|
||||
(if (not bookmark-alist)
|
||||
(if (file-readable-p bookmark-file)
|
||||
(bookmark-load bookmark-file)))
|
||||
(if bookmark-alist
|
||||
(mapcar (lambda (cell)
|
||||
(let ((str (car cell)))
|
||||
(cons
|
||||
(if (> (length str) bookmark-menu-length)
|
||||
(substring str 0 bookmark-menu-length)
|
||||
str)
|
||||
str)))
|
||||
bookmark-alist)
|
||||
(error "No bookmarks currently set.")))
|
||||
|
||||
(defun bookmark-make-menu-with-function (func-sym menu-label menu-str event)
|
||||
;; help function for making menus that need to apply a bookmark
|
||||
;; function to a string.
|
||||
(let* ((menu (bookmark-make-menu-alist))
|
||||
(str (x-popup-menu event
|
||||
(list menu-label
|
||||
(cons menu-str
|
||||
menu)))))
|
||||
(if str
|
||||
(apply func-sym (list str)))))
|
||||
|
||||
(defun bookmark-menu-insert (event)
|
||||
"Insert the text of the file pointed to by bookmark BOOKMARK. You
|
||||
may have a problem using this function if the value of variable
|
||||
bookmark-alist is nil. If that happens, you need to load in some
|
||||
bookmarks. See help on function bookmark-load for more about this."
|
||||
(interactive "e")
|
||||
(bookmark-make-menu-with-function 'bookmark-insert
|
||||
"Bookmark Insert Menu"
|
||||
"--- Insert Contents ---"
|
||||
event))
|
||||
|
||||
(defun bookmark-menu-jump (event)
|
||||
"Go to the location saved in the bookmark BOOKMARK. You may have a
|
||||
problem using this function if the value of variable bookmark-alist
|
||||
is nil. If that happens, you need to load in some bookmarks. See
|
||||
help on function bookmark-load for more about this."
|
||||
(interactive "e")
|
||||
(bookmark-make-menu-with-function 'bookmark-jump
|
||||
"Bookmark Jump Menu"
|
||||
"--- Jump to Bookmark ---"
|
||||
event))
|
||||
|
||||
(defun bookmark-menu-locate (event)
|
||||
"Insert the name of the file associated with BOOKMARK \(as opposed
|
||||
to the contents of that file\)."
|
||||
(interactive "e")
|
||||
(bookmark-make-menu-with-function 'bookmark-locate
|
||||
"Bookmark Locate Menu"
|
||||
"--- Insert Location ---"
|
||||
event))
|
||||
|
||||
(defun bookmark-menu-rename (event)
|
||||
"Change the name of BOOKMARK to NEWNAME. While you are entering
|
||||
the new name, consecutive C-w\'s will insert consectutive words from
|
||||
the text of the buffer into the new bookmark name, and C-v will insert
|
||||
the name of the file."
|
||||
(interactive "e")
|
||||
(bookmark-make-menu-with-function 'bookmark-rename
|
||||
"Bookmark Rename Menu"
|
||||
"--- Rename Bookmark ---"
|
||||
event))
|
||||
|
||||
(defun bookmark-menu-delete (event)
|
||||
"Delete the bookmark named NAME from the bookmark list. Removes only
|
||||
the first instance of a bookmark with that name. If there is another
|
||||
bookmark with the same name, it will become \"current\" as soon as the
|
||||
old one is removed from the bookmark list."
|
||||
(interactive "e")
|
||||
(bookmark-make-menu-with-function 'bookmark-delete
|
||||
"Bookmark Delete Menu"
|
||||
"--- Delete Bookmark ---"
|
||||
event))
|
||||
|
||||
(defun bookmark-menu-delete-all ()
|
||||
(interactive)
|
||||
(let ((current-prefix-arg t))
|
||||
(bookmark-delete nil)))
|
||||
|
||||
(if (and bookmark-enable-menus window-system)
|
||||
(progn
|
||||
(defvar menu-bar-bookmark-map
|
||||
(make-sparse-keymap "Bookmark functions"))
|
||||
|
||||
;; make bookmarks appear toward the right side of the menu.
|
||||
(if (boundp 'menu-bar-final-items)
|
||||
(if menu-bar-final-items
|
||||
(setq menu-bar-final-items
|
||||
(cons 'bookmark menu-bar-final-items)))
|
||||
(setq menu-bar-final-items '(bookmark)))
|
||||
|
||||
(define-key global-map [menu-bar bookmark]
|
||||
(cons "Bookmarks" menu-bar-bookmark-map))
|
||||
|
||||
(define-key menu-bar-bookmark-map [load]
|
||||
'(" Load a bookmark file" . bookmark-load))
|
||||
|
||||
(define-key menu-bar-bookmark-map [write]
|
||||
'("Write \(to another file\)" . bookmark-write))
|
||||
|
||||
(define-key menu-bar-bookmark-map [save]
|
||||
'("Save \(in default file\)" . bookmark-save))
|
||||
|
||||
(define-key menu-bar-bookmark-map [delete-all]
|
||||
'(" Delete all bookmarks" . bookmark-menu-delete-all))
|
||||
|
||||
(define-key menu-bar-bookmark-map [delete]
|
||||
'(" Delete a bookmark" . bookmark-menu-delete))
|
||||
|
||||
(define-key menu-bar-bookmark-map [rename]
|
||||
'(" Rename bookmark" . bookmark-menu-rename))
|
||||
|
||||
(define-key menu-bar-bookmark-map [locate]
|
||||
'(" Insert location" . bookmark-menu-locate))
|
||||
|
||||
(define-key menu-bar-bookmark-map [insert]
|
||||
'(" Insert contents" . bookmark-menu-insert))
|
||||
|
||||
(define-key menu-bar-bookmark-map [set]
|
||||
'(" Set bookmark" . bookmark-set))
|
||||
|
||||
(define-key menu-bar-bookmark-map [jump]
|
||||
'(" Go to bookmark" . bookmark-menu-jump))))
|
||||
|
||||
;; not using properties because they make the menu sluggish in coming
|
||||
;; up -- too many tests to make. Instead, choosing a useless menu
|
||||
;; item just gets you an error now (see
|
||||
;; bookmark-make-menu-with-function)
|
||||
;;
|
||||
;; (put 'bookmark-menu-jump 'menu-enable
|
||||
;; '(or bookmark-alist
|
||||
;; (and (file-readable-p bookmark-file)
|
||||
;; (progn (bookmark-load bookmark-file)
|
||||
;; bookmark-alist))))
|
||||
;;
|
||||
;; (put 'bookmark-menu-insert 'menu-enable
|
||||
;; '(or bookmark-alist
|
||||
;; (and (file-readable-p bookmark-file)
|
||||
;; (progn (bookmark-load bookmark-file)
|
||||
;; bookmark-alist))))
|
||||
;;
|
||||
;; (put 'bookmark-menu-locate 'menu-enable
|
||||
;; '(or bookmark-alist
|
||||
;; (and (file-readable-p bookmark-file)
|
||||
;; (progn (bookmark-load bookmark-file)
|
||||
;; bookmark-alist))))
|
||||
;;
|
||||
;; (put 'bookmark-menu-rename 'menu-enable
|
||||
;; '(or bookmark-alist
|
||||
;; (and (file-readable-p bookmark-file)
|
||||
;; (progn (bookmark-load bookmark-file)
|
||||
;; bookmark-alist))))
|
||||
;;
|
||||
;; (put 'bookmark-menu-delete 'menu-enable
|
||||
;; '(or bookmark-alist
|
||||
;; (and (file-readable-p bookmark-file)
|
||||
;; (progn (bookmark-load bookmark-file)
|
||||
;; bookmark-alist))))
|
||||
;;
|
||||
;; (put 'bookmark-menu-save 'menu-enable
|
||||
;; '(or bookmark-alist
|
||||
;; (and (file-readable-p bookmark-file)
|
||||
;; (progn (bookmark-load bookmark-file)
|
||||
;; bookmark-alist))))
|
||||
;;
|
||||
;; (put 'bookmark-menu-write 'menu-enable
|
||||
;; '(or bookmark-alist
|
||||
;; (and (file-readable-p bookmark-file)
|
||||
;; (progn (bookmark-load bookmark-file)
|
||||
;; bookmark-alist))))
|
||||
|
||||
;;;; end bookmark menu stuff ;;;;
|
||||
|
||||
;; load the default bookmark file, if it exists, and the
|
||||
;; bookmark-alist is nil:
|
||||
(bookmark-try-default-file)
|
||||
|
||||
|
||||
(provide 'bookmark)
|
||||
|
||||
;;; bookmark.el ends here ;;;
|
Loading…
Reference in New Issue
Block a user