| @@ -153,6 +153,7 @@ found, otherwise returns nil." | |||
| ilookup | |||
| pasteboard | |||
| awk-preview | |||
| recently | |||
| )) | |||
| @@ -708,6 +709,9 @@ found, otherwise returns nil." | |||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
| ;; file handling | |||
| (when (safe-require-or-eval 'recently) | |||
| (recently-mode 1)) | |||
| (when (safe-require-or-eval 'editorconfig) | |||
| ;; (set-variable 'editorconfig-get-properties-function | |||
| ;; 'editorconfig-core-get-properties-hash) | |||
| @@ -1812,243 +1816,6 @@ and search from projectile root (if projectile is available)." | |||
| (editorconfig-auto-apply-mode 1) | |||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
| ;; recently | |||
| (defgroup recently nil | |||
| "Recently visited files" | |||
| :tag "Recently" | |||
| :prefix "recently-" | |||
| :group 'tools) | |||
| (defcustom recently-file | |||
| (concat user-emacs-directory | |||
| "recently.el") | |||
| "Recently file." | |||
| :type 'string | |||
| :group 'recently) | |||
| (defcustom recently-max | |||
| 100 | |||
| "Recently list max length." | |||
| :type 'int | |||
| :group 'recently) | |||
| (defcustom recently-excludes | |||
| '() | |||
| "List of regexps for filenames excluded from the recent list." | |||
| :type '(repeat string) | |||
| :group 'recently) | |||
| (add-to-list 'recently-excludes | |||
| (eval-when-compile (rx "/COMMIT_EDITMSG" eot))) | |||
| (defvar recently-list | |||
| '() | |||
| "Recently list.") | |||
| (defvar recently-file-mtime | |||
| nil | |||
| "Modified time of file when last read file.") | |||
| (defun recently-write () | |||
| "Write to file." | |||
| ;; Failsafe to avoid purging all existing entries | |||
| (cl-assert recently-list) | |||
| (with-temp-buffer | |||
| (prin1 recently-list | |||
| (current-buffer)) | |||
| (write-region (point-min) | |||
| (point-max) | |||
| recently-file))) | |||
| (defun recently-read () | |||
| "Read file." | |||
| (when (file-readable-p recently-file) | |||
| (with-temp-buffer | |||
| (insert-file-contents recently-file) | |||
| (goto-char (point-min)) | |||
| (setq recently-list | |||
| (read (current-buffer)))) | |||
| (setq recently-file-mtime | |||
| (nth 5 | |||
| (file-attributes recently-file))))) | |||
| (defun recently-reload () | |||
| "Reload file and update `recently-list' value. | |||
| This function does nothing when there is no update to `recently-file' since last | |||
| read." | |||
| (when (and (file-readable-p recently-file) | |||
| (not (equal recently-file-mtime | |||
| (nth 5 | |||
| (file-attributes recently-file))))) | |||
| (recently-read) | |||
| (cl-assert (equal recently-file-mtime | |||
| (nth 5 | |||
| (file-attributes recently-file)))))) | |||
| (defun recently-add (path) | |||
| "Add PATH to list." | |||
| (cl-assert (string= path | |||
| (expand-file-name path))) | |||
| (when (cl-loop for re in recently-excludes | |||
| if (string-match re path) return nil | |||
| finally return t) | |||
| (recently-reload) | |||
| (let* ((l (cl-copy-list recently-list)) | |||
| (l (delete path | |||
| l)) | |||
| (l (cl-loop for e in l | |||
| unless (file-in-directory-p path e) | |||
| collect e)) | |||
| (l (cons path | |||
| l)) | |||
| (l (recently--truncate l | |||
| recently-max))) | |||
| (unless (equal recently-list | |||
| l) | |||
| (setq recently-list l) | |||
| (recently-write) | |||
| (setq recently-file-mtime | |||
| (nth 5 | |||
| (file-attributes recently-file))))))) | |||
| (defun recently--truncate (list len) | |||
| "Truncate LIST to LEN." | |||
| (if (> (length list) | |||
| len) | |||
| (cl-subseq list | |||
| 0 | |||
| len) | |||
| list)) | |||
| (defun recently-find-file-hook () | |||
| "Add current file." | |||
| (when buffer-file-name | |||
| (recently-add buffer-file-name))) | |||
| (defun recently-dired-mode-hook () | |||
| "Add current directory." | |||
| (recently-add (expand-file-name default-directory))) | |||
| (add-hook 'find-file-hook | |||
| 'recently-find-file-hook) | |||
| (add-hook 'dired-mode-hook | |||
| 'recently-dired-mode-hook) | |||
| ;;;;;;;;;;;;;;;; | |||
| ;; recently-show | |||
| (defvar recently-show-window-configuration nil | |||
| "Used for internal") | |||
| (defvar recently-show-abbreviate t | |||
| "Non-nil means use `abbreviate-file-name' when listing recently opened files.") | |||
| ;;;###autoload | |||
| (defun recently-show (&optional buffer-name) | |||
| "Show simplified list of recently opened files. | |||
| If optional argument BUFFER-NAME is non-nil, it is a buffer name to | |||
| use for the buffer. It defaults to \"*recetf-show*\"." | |||
| ;; If optional argument FILES is non-nil, it is a list of recently-opened | |||
| ;; files to choose from. It defaults to the whole recent list. | |||
| (interactive) | |||
| (let ((bf (recently-show--create-buffer-tabulated buffer-name))) | |||
| (if bf | |||
| (progn | |||
| (setq recently-show-window-configuration (current-window-configuration)) | |||
| (pop-to-buffer bf)) | |||
| (message "No recent file!")))) | |||
| (defun recently-show--create-buffer-tabulated (&optional buffer-name) | |||
| "Create buffer listing recently files." | |||
| (let ((bname (or buffer-name | |||
| "*Recently*"))) | |||
| (when (get-buffer bname) | |||
| (kill-buffer bname)) | |||
| (with-current-buffer (get-buffer-create bname) | |||
| ;; (setq tabulated-list-sort-key (cons "Name" nil)) | |||
| (recently-show--set-tabulated-list-mode-variables) | |||
| (recently-show-tabulated-mode) | |||
| (current-buffer)))) | |||
| (defun recently-show--set-tabulated-list-mode-variables () | |||
| "Set variables for `tabulated-list-mode'." | |||
| (recently-reload) | |||
| (setq tabulated-list-entries | |||
| (mapcar (lambda (f) | |||
| (list f | |||
| (vector (file-name-nondirectory f) | |||
| (if recently-show-abbreviate | |||
| (abbreviate-file-name f) | |||
| f)))) | |||
| recently-list | |||
| )) | |||
| (let ((max | |||
| (apply 'max | |||
| (mapcar (lambda (l) | |||
| (length (elt (cadr l) 0))) | |||
| tabulated-list-entries)))) | |||
| (setq tabulated-list-format | |||
| `[("Name" | |||
| ,(min max | |||
| 30) | |||
| t) | |||
| ("Full Path" 0 t)]))) | |||
| (defun recently-show-tabulated-find-file () | |||
| "Find file at point." | |||
| (interactive) | |||
| (let ((f (tabulated-list-get-id))) | |||
| (cl-assert f nil "No entry at point") | |||
| (recently-show-tabulated-close) | |||
| (find-file f))) | |||
| (defun recently-show-tabulated-view-file () | |||
| "View file at point." | |||
| (interactive) | |||
| (let ((f (tabulated-list-get-id))) | |||
| (cl-assert f nil "No entry at point") | |||
| (recently-show-tabulated-close) | |||
| (view-file f))) | |||
| (defun recently-show-tabulated-dired() | |||
| "Open dired buffer of directory at point." | |||
| (interactive) | |||
| (let ((f (tabulated-list-get-id))) | |||
| (cl-assert f nil "No entry at point") | |||
| (recently-show-tabulated-close) | |||
| (dired (if (file-directory-p f) | |||
| f | |||
| (or (file-name-directory f) | |||
| "."))))) | |||
| (defvar recently-show-tabulated-mode-map | |||
| (let ((map (make-sparse-keymap))) | |||
| (suppress-keymap map) | |||
| (define-key map (kbd "C-m") 'recently-show-tabulated-find-file) | |||
| (define-key map "v" 'recently-show-tabulated-view-file) | |||
| (define-key map "@" 'recently-show-tabulated-dired) | |||
| (define-key map (kbd "C-g") 'recently-show-tabulated-close) | |||
| (define-key map "/" 'isearch-forward) | |||
| map)) | |||
| (define-derived-mode recently-show-tabulated-mode tabulated-list-mode "Recently-Show" | |||
| "Major mode for browsing recently opened files and directories." | |||
| (setq tabulated-list-padding 2) | |||
| (add-hook 'tabulated-list-revert-hook | |||
| 'recently-show--set-tabulated-list-mode-variables | |||
| nil | |||
| t) | |||
| (tabulated-list-init-header) | |||
| (tabulated-list-print nil nil)) | |||
| (defun recently-show-tabulated-close () | |||
| "Close recently-show window." | |||
| (interactive) | |||
| (kill-buffer (current-buffer)) | |||
| (set-window-configuration recently-show-window-configuration)) | |||
| (define-key ctl-x-map (kbd "C-r") 'recently-show) | |||