;; ----------------------------------------------------------------- ;; edit-history.el -- Maintain a menu of recently accessed files and ;; buffers. ;; ;; Author: Mic Bowman (mic@transarc.com) ;; ----------------------------------------------------------------- (require 'cl) (add-hook 'find-file-hooks 'ehistory-add-to-history) (add-hook 'kill-emacs-hook 'ehistory-save-file-list) ;(add-hook 'kill-buffer-hook 'ehistory-kill-buffer) ;; ----------------------------------------------------------------- (defvar ehistory-history-file "~/.emacs_ehistory" "File for saving edit history between sessions.") ;; ----------------------------------------------------------------- (defvar ehistory-history-length 20 "Length of file history.") ;; ----------------------------------------------------------------- (defvar ehistory-ignore-regexp "/\\(browse\\|diary\\|site-diary\\|tags\\|.*rmail.*\\|.*\.tmp\\)$" "Regexp of files not to add to `ehistory-file-list'.") ;; ----------------------------------------------------------------- (defvar ehistory-file-list nil "List of most recently accessed files.") ;; ----------------------------------------------------------------- ; ehistory-add-to-history ; ; Add a file to the list of recently accessed files. This function ; should be called from the find-file-hooks when a file is loaded. ;; ----------------------------------------------------------------- (defun ehistory-add-to-history () (let ((fname (buffer-file-name)) (hlist ehistory-file-list) (hlen (1- ehistory-history-length))) (if (and (not (string= fname (expand-file-name ehistory-history-file))) (not (string-match ehistory-ignore-regexp fname))) (progn (setq ehistory-file-list (cons fname (ehistory-clean fname hlist hlen))) (ehistory-update-menu-bar))))) ;; ----------------------------------------------------------------- ; ehistory-clean ; ; Clean the history list. Remove the new file from the list and ; truncate it to the correct length. ;; ----------------------------------------------------------------- (defun ehistory-clean (fname hlist hlen) (cond ((null hlist) nil) ((= hlen 0) nil) ((string= fname (car hlist)) (ehistory-clean fname (cdr hlist) (1- hlen))) ((cons (car hlist) (ehistory-clean fname (cdr hlist) (1- hlen)))))) ;; ----------------------------------------------------------------- ; ehistory-save-file-list ; ; Save the file access history list. This should be added as a hook to ; kill-emacs-hook. ;; ----------------------------------------------------------------- (defun ehistory-save-file-list () "Save the file access history list." (interactive) (save-excursion (let ((file ehistory-history-file)) (message (format "Saving edit history to file %s." file)) (set-buffer (find-file-noselect file)) (goto-char (point-min)) (delete-region (point-min) (point-max)) (print ehistory-file-list (current-buffer)) (write-file file) (kill-buffer (current-buffer))))) ;; ----------------------------------------------------------------- ; ehistory-load-file-list ; ; Load an edit history file. This should be called in the startup ; code. ;; ----------------------------------------------------------------- (defun ehistory-load-file-list () "Load the edit history file specified in the variable ehistory-history-file." (interactive) (let ((file ehistory-history-file)) (setq ehistory-file-list nil) (if (file-readable-p file) (save-excursion (message (format "Loading edit history from %s..." file)) (set-buffer (find-file-noselect file)) (goto-char (point-min)) (setq ehistory-file-list (read (current-buffer))) (kill-buffer (current-buffer))) (message (format "Unable to load history from %s..." file))) (ehistory-update-menu-bar))) ;; ----------------------------------------------------------------- ; ehistory-files-menu ; ; Popup a menu of recently edited files. ;; ----------------------------------------------------------------- (defun ehistory-files-menu (flist) (if (null flist) nil (cons (nconc (list (car flist) (car flist) (cons nil nil)) 'ehistory-find-file) (ehistory-files-menu (cdr flist))))) ;;; ----------------------------------------------------------------- ;; ehistory-buffers-menu ;; ;; A faster and more useful (for me) buffer menu. ;;; ----------------------------------------------------------------- ;(defun ehistory-buffer-menu (blist) ; (cond ((null blist) nil) ; ((string-match " *\\*" (buffer-name (car blist))) ; (ehistory-buffer-menu (cdr blist))) ; ((cons ; (nconc (list (buffer-name (car blist)) ; (buffer-name (car blist)) ; (cons nil nil)) ; 'ehistory-select-buffer) ; (ehistory-buffer-menu (cdr blist)))))) ;(defun ehistory-current-buffer (buf) ; (equal (buffer-name (current-buffer)) (car buf))) ;(defun ehistory-kill-buffer () ; (let ((menu (remove-if 'ehistory-current-buffer ehistory-last-buffer-list))) ; (setq ehistory-last-buffer-list menu) ; (setq menu (cons 'keymap (cons "Select Buffer" menu))) ; (define-key global-map [menu-bar buffer] ; (cons "Buffers" menu)))) ;; ----------------------------------------------------------------- ; ehistory-update-menu-bar ;; ----------------------------------------------------------------- (defvar ehistory-last-buffer-list nil) (defvar ehistory-last-file-list nil) (defvar ehistory-update-count 0) (defun ehistory-update-menu-bar () ; (let ((bmenu (ehistory-buffer-menu (buffer-list))) ; (fmenu (ehistory-files-menu ehistory-file-list))) ; (setq ehistory-update-count (+ 1 ehistory-update-count)) ; (if (not (equal bmenu ehistory-last-buffer-list)) ; (progn ; (setq ehistory-last-buffer-list bmenu) ; (setq bmenu (cons 'keymap (cons "Select Buffer" bmenu))) ; (define-key global-map [menu-bar buffer] ; (cons "Buffers" bmenu)))) ; (if (not (equal fmenu ehistory-last-file-list)) ; (progn ; (setq ehistory-last-file-list fmenu) ; (setq fmenu (cons 'keymap (cons "Select File" fmenu))) ; (define-key global-map [menu-bar history] ; (cons "History" fmenu)))))) (let ((fmenu (ehistory-files-menu ehistory-file-list))) (setq ehistory-update-count (+ 1 ehistory-update-count)) (if (not (equal fmenu ehistory-last-file-list)) (progn (setq ehistory-last-file-list fmenu) (setq fmenu (cons 'keymap (cons "Select File" fmenu))) (define-key global-map [menu-bar history] (cons "*" fmenu)))))) ;; ----------------------------------------------------------------- (defun ehistory-find-file () (interactive) (find-file last-command-event)) (defun ehistory-select-buffer () (interactive) (switch-to-buffer last-command-event)) ;; ----------------------------------------------------------------- ;(if (member 'menu-bar-update-buffers menu-bar-update-hook) ; (remove-hook 'menu-bar-update-hook 'menu-bar-update-buffers))