;;; Code:
(require 'easymenu)
+(require 'widget)
+(eval-when-compile
+ (require 'wid-edit))
(defconst recentf-save-file-header
";;; Automatically generated by `recentf' on %s.\n"
The default action `recentf-find-file' calls `find-file' to edit an
existing file. If the file does not exist or is not readable, it is
not edited and its name is removed from `recentf-list'. You can use
-`find-file' instead to open non-existing files and keep them is the
+`find-file' instead to open non-existing files and keep them in the
list of recently opened files."
:group 'recentf
:type 'function
When recentf mode is enabled, it maintains a menu for visiting files that
were operated on recently."
(interactive "P")
- (when window-system
- (let ((on-p (if arg
- (> (prefix-numeric-value arg) 0)
- (not recentf-mode))))
- (if on-p
- (unless recentf-initialized-p
- (setq recentf-initialized-p t)
- (if (file-readable-p recentf-save-file)
- (load-file recentf-save-file))
- (setq recentf-update-menu-p t)
- (add-hook 'find-file-hooks 'recentf-add-file-hook)
- (add-hook 'write-file-hooks 'recentf-add-file-hook)
- ;; (add-hook 'activate-menubar-hook 'recentf-update-menu-hook)
- (add-hook 'menu-bar-update-hook 'recentf-update-menu-hook)
- (add-hook 'kill-emacs-hook 'recentf-save-list))
- (when recentf-initialized-p
- (setq recentf-initialized-p nil)
- (recentf-save-list)
- (easy-menu-remove-item nil recentf-menu-path recentf-menu-title)
- (remove-hook 'find-file-hooks 'recentf-add-file-hook)
- (remove-hook 'write-file-hooks 'recentf-add-file-hook)
- ;; (remove-hook 'activate-menubar-hook 'recentf-update-menu-hook)
- (remove-hook 'menu-bar-update-hook 'recentf-update-menu-hook)
- (remove-hook 'kill-emacs-hook 'recentf-save-list)))
- (setq recentf-mode on-p))))
+ (let ((on-p (if arg
+ (> (prefix-numeric-value arg) 0)
+ (not recentf-mode))))
+ (if on-p
+ (unless recentf-initialized-p
+ (setq recentf-initialized-p t)
+ (if (file-readable-p recentf-save-file)
+ (load-file recentf-save-file))
+ (setq recentf-update-menu-p t)
+ (add-hook 'find-file-hooks 'recentf-add-file-hook)
+ (add-hook 'write-file-hooks 'recentf-add-file-hook)
+ ;; (add-hook 'activate-menubar-hook 'recentf-update-menu-hook)
+ (add-hook 'menu-bar-update-hook 'recentf-update-menu-hook)
+ (add-hook 'kill-emacs-hook 'recentf-save-list))
+ (when recentf-initialized-p
+ (setq recentf-initialized-p nil)
+ (recentf-save-list)
+ (easy-menu-remove-item nil recentf-menu-path recentf-menu-title)
+ (remove-hook 'find-file-hooks 'recentf-add-file-hook)
+ (remove-hook 'write-file-hooks 'recentf-add-file-hook)
+ ;; (remove-hook 'activate-menubar-hook 'recentf-update-menu-hook)
+ (remove-hook 'menu-bar-update-hook 'recentf-update-menu-hook)
+ (remove-hook 'kill-emacs-hook 'recentf-save-list)))
+ (setq recentf-mode on-p)))
(defun recentf-add-file-hook ()
"Insert the name of the file just opened or written into `recentf-list'."
(kill-buffer (current-buffer))))
nil)
+(defvar recentf-edit-selected-items nil
+ "Used by `recentf-edit-list' to hold the list of files to be deleted
+from `recentf-list'.")
+
+(defun recentf-edit-list-action (widget &rest ignore)
+ "Checkbox widget action used by `recentf-edit-list' to select/unselect a file."
+ (let ((value (widget-get widget ':tag)))
+ ;; if value is already in the selected items
+ (if (memq value recentf-edit-selected-items)
+ ;; then remove it
+ (progn
+ (setq recentf-edit-selected-items
+ (delq value recentf-edit-selected-items))
+ (message "%s removed from selection." value))
+ ;; else add it
+ (progn
+ (setq recentf-edit-selected-items
+ (nconc (list value) recentf-edit-selected-items))
+ (message "%s added to selection." value)))))
+
+;;;###autoload
+(defun recentf-edit-list ()
+ "Allow the user to edit the files that are kept in the recent list."
+ (interactive)
+ (with-current-buffer (get-buffer-create (concat "*" recentf-menu-title " - Edit list*"))
+ (switch-to-buffer (current-buffer))
+ (kill-all-local-variables)
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ (let ((all (overlay-lists)))
+ ;; Delete all the overlays.
+ (mapcar 'delete-overlay (car all))
+ (mapcar 'delete-overlay (cdr all)))
+ (setq recentf-edit-selected-items nil)
+ ;; Insert the dialog header
+ (widget-insert "Select the files to be deleted from the 'recentf-list'.\n\n")
+ (widget-insert "Click on Ok to update the list or on Cancel to quit.\n" )
+ ;; Insert the list of files as checkboxes
+ (mapcar '(lambda (item)
+ (widget-create 'checkbox
+ :value nil ; unselected checkbox
+ :format "\n %[%v%] %t"
+ :tag item
+ :notify 'recentf-edit-list-action))
+ recentf-list)
+ (widget-insert "\n\n")
+ ;; Insert the Ok button
+ (widget-create 'push-button
+ :notify (lambda (&rest ignore)
+ (if recentf-edit-selected-items
+ (progn (kill-buffer (current-buffer))
+ (mapcar '(lambda (item)
+ (setq recentf-list
+ (delq item recentf-list)))
+ recentf-edit-selected-items)
+ (message "%S file(s) removed from the list"
+ (length recentf-edit-selected-items))
+ (setq recentf-update-menu-p t))
+ (message "No file selected.")))
+ "Ok")
+ (widget-insert " ")
+ ;; Insert the Cancel button
+ (widget-create 'push-button
+ :notify (lambda (&rest ignore)
+ (kill-buffer (current-buffer))
+ (message "Command canceled."))
+ "Cancel")
+ (use-local-map widget-keymap)
+ (widget-setup)))
+
;;;###autoload
(defun recentf-cleanup ()
- "Remove all non-readable files from `recentf-list'."
+ "Remove all non-readable and excluded files from `recentf-list'."
(interactive)
- (setq recentf-list (delq nil (mapcar '(lambda (f)
- (and (file-readable-p f) f))
- recentf-list)))
+ (setq recentf-list
+ (delq nil
+ (mapcar '(lambda (filename)
+ (and (file-readable-p filename)
+ (recentf-include-p filename)
+ filename))
+ recentf-list)))
(setq recentf-update-menu-p t))
+(defun recentf-open-more-files-action (widget &rest ignore)
+ "Button widget action used by `recentf-open-more-files' to open a file."
+ (kill-buffer (current-buffer))
+ (funcall recentf-menu-action (widget-value widget)))
+
+;;;###autoload
+(defun recentf-open-more-files ()
+ "Allow the user to open files that are not in the menu."
+ (interactive)
+ (with-current-buffer (get-buffer-create (concat "*" recentf-menu-title " - More*"))
+ (switch-to-buffer (current-buffer))
+ (kill-all-local-variables)
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ (let ((all (overlay-lists)))
+ ;; Delete all the overlays.
+ (mapcar 'delete-overlay (car all))
+ (mapcar 'delete-overlay (cdr all)))
+ ;; Insert the dialog header
+ (widget-insert "Click on a file to open it or on Cancel to quit.\n\n")
+ ;; Insert the list of files as buttons
+ (mapcar '(lambda (menu-element)
+ (let ((menu-item (car menu-element))
+ (file-path (cdr menu-element)))
+ (widget-create 'push-button
+ :button-face 'default
+ :tag menu-item
+ :help-echo (concat "Open " file-path)
+ :format "%[%t%]"
+ :notify 'recentf-open-more-files-action
+ file-path)
+ (widget-insert "\n")))
+ (funcall (or recentf-menu-filter 'identity)
+ (mapcar '(lambda (item) (cons item item))
+ (nthcdr recentf-max-menu-items recentf-list))))
+ (widget-insert "\n")
+ ;; Insert the Cancel button
+ (widget-create 'push-button
+ :notify (lambda (&rest ignore)
+ (kill-buffer (current-buffer))
+ (message "Command canceled."))
+ "Cancel")
+ (use-local-map widget-keymap)
+ (widget-setup)))
+
(defvar recentf-menu-items-for-commands
(list ["Cleanup list" recentf-cleanup t]
+ ["Edit list..." recentf-edit-list t]
["Save list now" recentf-save-list t]
- (vector (format "Recentf Options...")
- '(customize-group "recentf") t))
+ (vector "Recentf Options..." '(customize-group "recentf") t))
"List of menu items for recentf commands.")
(defun recentf-make-menu-items ()
(funcall (or recentf-menu-filter 'identity)
(recentf-elements recentf-max-menu-items)))))
(append (or file-items (list ["No files" t nil]))
+ (and (< recentf-max-menu-items (length recentf-list))
+ (list ["More..." recentf-open-more-files t]))
(and recentf-menu-append-commands-p
(cons ["---" nil nil]
recentf-menu-items-for-commands)))))