emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

request review for minor change (bookmark.el, kill-emacs-hook)


From: Karl Fogel
Subject: request review for minor change (bookmark.el, kill-emacs-hook)
Date: 10 Nov 2000 07:33:40 -0600

I received mail from a user who wants a `bookmark-exit-hook', to be
run from kill-emacs-hook, so he can implement something.

Since the `bookmark-exit-hook' is of general utility, I'm inclined to
make the change, but there may be "gotchas" regarding kill-emacs-hook
that I'm not experienced with.

So if anyone has comments about his patch, please let me know.  The
original mail, which includes his explanation of why he needs this, is
included at the bottom of the message.

   *** bookmark.el Sat Jul 18 23:37:52 1998
   --- bookmark.el Fri Sep 24 15:50:12 1999
   ***************
   *** 326,335 ****
     ;;;###autoload
     (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.
     
   --- 326,336 ----
     ;;;###autoload
     (add-hook 'kill-emacs-hook
               (function
   !          (lambda () (and (featurep 'bookmark)
   !                          (progn (run-hooks 'bookmark-exit-hook) t)
   !                          bookmark-alist
   !                          (bookmark-time-to-save-p t)
   !                          (bookmark-save)))))
     
     ;; more stuff added by db.
     
   ***************
   *** 2288,2293 ****
   --- 2289,2298 ----
     ;;; Load Hook
     (defvar bookmark-load-hook nil
       "Hook to run at the end of loading bookmark.")
   + 
   + ;;; Exit Hook, called from kill-emacs-hook
   + (defvar bookmark-exit-hook nil
   +   "Hook to run when emacs exits")
     
     (run-hooks 'bookmark-load-hook)
  

And here is Ovidiu Predescu's original message:


------- Start of forwarded message -------
Message-Id: <address@hidden>
From: Ovidiu Predescu <address@hidden>
To: Steve Baur <address@hidden>
Cc: Karl Fogel <address@hidden>
Subject: Netscape-like navigation in source files and bookmark.el patch
Date: Fri, 24 Sep 1999 16:10:31 -0700

Hi,

I implemented a neat feature in Xemacs that allows one to setup bookmarks and
navigate between them just like in Netscape, using Meta-left and Meta-right.
The feature is integrated with etags, each time you request a definition of a
symbol, it automatically sets up a bookmark at the current location and then
moves to the definition. You can also setup a new bookmark using a combination
of keys, it will be added to the ring of bookmarks you can navigate between.

While implementing this I needed a hook in bookmark.el to be invoked before the
automatic hook that's setup in the file. Below is the patch for it. Could you
please include it in the next release of edit-utils? I don't think it breaks
anything.

*** bookmark.el.old     Sat Jul 18 23:37:52 1998
--- bookmark.el Fri Sep 24 15:50:12 1999
***************
*** 326,335 ****
  ;;;###autoload
  (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.
  
--- 326,336 ----
  ;;;###autoload
  (add-hook 'kill-emacs-hook
            (function
!          (lambda () (and (featurep 'bookmark)
!                          (progn (run-hooks 'bookmark-exit-hook) t)
!                          bookmark-alist
!                          (bookmark-time-to-save-p t)
!                          (bookmark-save)))))
  
  ;; more stuff added by db.
  
***************
*** 2288,2293 ****
--- 2289,2298 ----
  ;;; Load Hook
  (defvar bookmark-load-hook nil
    "Hook to run at the end of loading bookmark.")
+ 
+ ;;; Exit Hook, called from kill-emacs-hook
+ (defvar bookmark-exit-hook nil
+   "Hook to run when emacs exits")
  
  (run-hooks 'bookmark-load-hook)
  

And here is the code for the feature I've implemented. Note that I'm a beginner
with Emacs Lisp (although a long-time user of Xemacs), so some of the things
could be done in a different way. I have this piece of code in my .emacs.


;; Use a Netscape-like navigation when working with etags and bookmarks.
(setq current-bookmark nil)
(setq bookmark-stack (list))
(setq bookmark-redo-stack (list))

(defun reduce (function alist)
  (if (not (null alist))
      (let ((arg (car alist)))
        (if (apply function (list arg))
            (cons arg (reduce function (cdr alist)))
          (reduce function (cdr alist))))
    nil))

(defun bookmarks-equal (bk1 bk2)
  (if (or (null bk1) (null bk2))
      nil
    (and (string= (bookmark-get-filename bk1)
                  (bookmark-get-filename bk2))
         (= (bookmark-get-position bk1) (bookmark-get-position bk2)))))

(defun setup-new-bookmark ()
  (interactive)
  ; First remove all the bookmarks from the redo stack
  (mapcar '(lambda (x) (bookmark-delete x t)) bookmark-redo-stack)
  (setq bookmark-redo-stack (list))
  ; Setup a temporary bookmark at this point and see if it's equal to
  ; the current-bookmark.  If so don't do anything as we want to avoid
  ; creating multiple bookmarks at the same point.
  (let ((temp "temporary"))
    (bookmark-set temp)
    (if (not (bookmarks-equal temp current-bookmark))
        ; Move the current-bookmark into bookmark-stack
        (progn
          (if current-bookmark
              (setq bookmark-stack (cons current-bookmark bookmark-stack)))
          (if (null bookmark-stack)
              (setq current-bookmark "1")
            (setq current-bookmark
                  (number-to-string
                   (1+ (string-to-number (car bookmark-stack))))))
          (bookmark-set current-bookmark)
          (message "Bookmark set.")))
    (bookmark-delete temp)))

(defun delete-bookmark ()
  (interactive)
  ; Setup a temporary bookmark at this point and check if it's equal
  ; to the current-bookmark; if so remove the current-breakpoint
  (let ((temp "temporary"))
    (bookmark-set temp)
    (if (bookmarks-equal temp current-bookmark)
        (progn
          (message "Bookmark removed.")
          (bookmark-delete current-bookmark)
          (setq current-bookmark nil)))
    (bookmark-delete temp)))

(defun my-find-tag ()
  (interactive)
  ;; Remember the current position
  (setup-new-bookmark)
  (find-tag (find-tag-tag "Find tag: "))
  (setup-new-bookmark))

(defun my-tags-loop-continue ()
  (interactive)
  (tags-loop-continue)
  (setup-new-bookmark))

(setq soundfile 'drum)

(defun tag-go-back ()
  (interactive)
  ; Try to move to the location of the last bookmark if we are in a
  ; different location than its position. We do this by setting up a
  ; temporary bookmark at this location and comparing it with the
  ; current-bookmark.
  (let ((temp "temporary"))
    (bookmark-set temp)
    (if (and (null current-bookmark) (not (null bookmark-stack)))
        ; Get the last element from bookmark-stack and assign it to
        ; current-bookmark
        (progn (setq current-bookmark (car bookmark-stack))
               (setq bookmark-stack (cdr bookmark-stack))))
    (if (and current-bookmark (not (bookmarks-equal temp current-bookmark)))
        (bookmark-jump current-bookmark)
      (if (null bookmark-stack)
          (progn (message "No more bookmarks.")
                 (play-sound soundfile 100))
        (progn (if current-bookmark
                   (setq bookmark-redo-stack
                         (cons current-bookmark bookmark-redo-stack)))
               (setq current-bookmark (car bookmark-stack))
               (setq bookmark-stack (cdr bookmark-stack))
               (bookmark-jump current-bookmark)
               nil)))
    (bookmark-delete temp)))

(defun tag-go-forward ()
  (interactive)
  (if (null bookmark-redo-stack)
      (progn (message "No more bookmarks.")
             (play-sound soundfile 100))
    (progn (if current-bookmark
               (setq bookmark-stack
                     (cons current-bookmark bookmark-stack)))
           (setq current-bookmark (car bookmark-redo-stack))
           (setq bookmark-redo-stack (cdr bookmark-redo-stack))
           (bookmark-jump current-bookmark)
           nil)))

(define-key global-map "\M-." 'my-find-tag)
(define-key global-map "\M-," 'my-tags-loop-continue)
(define-key global-map '(meta left) 'tag-go-back)
(define-key global-map '(meta right) 'tag-go-forward)
(define-key global-map '(control meta \.) 'setup-new-bookmark)
(define-key global-map '(control meta /) 'delete-bookmark)

(defvar bookmark-tags-file (convert-standard-filename "~/.emacs.pos"))

(defun load-bookmark-tags ()
  ;; Load the .emacs.pos file that contains the saved bookmarks from a
  ;; previous session.
  (let ((bookmark-alist-saved bookmark-alist)
        (error nil))
    (setq bookmark-alist nil)
    (condition-case nil
        (bookmark-load bookmark-tags-file)
      (error (setq error t)))
    (if (not error)
        ; We successfully read the bookmarks file. Get the name of the
        ; bookmarks and append them to bookmark-redo-stack.
        (progn
          (setq bookmark-redo-stack
                (reverse
                 (mapcar 'bookmark-name-from-full-record bookmark-alist)))
          (setq bookmark-alist-saved
                (append bookmark-alist-saved bookmark-redo-stack)))
      (setq bookmark-alist bookmark-alist-saved))))

(add-hook 'bookmark-load-hook 'load-bookmark-tags)

(defun bookmarks-update ()
  (if (not (featurep 'bookmark))
      nil
    (let* ((all-tags (append bookmark-stack
                             (list current-bookmark)
                             bookmark-redo-stack))
           (part-of-tags '(lambda (x)
                            (member (bookmark-name-from-full-record x)
                                    all-tags)))
           (not-part-of-tags '(lambda (x)
                                (not (member
                                      (bookmark-name-from-full-record x)
                                      all-tags))))
           (my-bookmarks (reduce part-of-tags bookmark-alist))
           (remaining-bookmarks (reduce not-part-of-tags bookmark-alist)))
      (setq bookmark-alist my-bookmarks)
      (bookmark-write-file bookmark-tags-file)
      (setq bookmark-alist remaining-bookmarks))))

(add-hook 'bookmark-exit-hook 'bookmarks-update)

(load "bookmark")



Best regards,
Ovidiu

------- End of forwarded message -------



reply via email to

[Prev in Thread] Current Thread [Next in Thread]