branch: elpa/dirvish commit 56b17ba36ffa300257b0536c14ebc13854920a80 Author: Alex Lu <hellosimon1...@hotmail.com> Commit: Alex Lu <hellosimon1...@hotmail.com>
refactor: use literal string for session/file id This prevents dirvish from polluting `obarray` with tons of meaningless symbol especially when entering directories with a lot of files or when `dirvish-reuse-session` is set to nil. --- dirvish-tramp.el | 4 +- dirvish.el | 107 +++++++++++++++++++++------------------------ extensions/dirvish-fd.el | 4 +- extensions/dirvish-peek.el | 4 +- extensions/dirvish-vc.el | 2 +- 5 files changed, 56 insertions(+), 65 deletions(-) diff --git a/dirvish-tramp.el b/dirvish-tramp.el index 189c27cb90..9638ec3d75 100644 --- a/dirvish-tramp.el +++ b/dirvish-tramp.el @@ -63,10 +63,10 @@ FN is the original `dired-noselect' closure." (f-truename (and sym (string-join (cl-subseq path (1+ sym)) " "))) (f-dirp (string-prefix-p "d" priv)) (f-type (or f-truename f-dirp))) - (puthash (intern (secure-hash 'md5 (expand-file-name f-name entry))) + (puthash (secure-hash 'md5 (expand-file-name f-name entry)) `(:builtin ,(list f-type lnum user group nil f-mtime nil size priv nil inode) - :type ,(cons (if f-dirp 'dir 'file) f-truename)) + :type ,(cons (if f-dirp 'dir 'file) f-truename)) dirvish--attrs-hash))))) (defun dirvish-tramp-dir-data-proc-s (proc _exit) diff --git a/dirvish.el b/dirvish.el index 0f4547e1a9..668db755c2 100644 --- a/dirvish.el +++ b/dirvish.el @@ -23,11 +23,10 @@ (require 'dired) (require 'transient) -(eval-when-compile (require 'subr-x)) +(eval-when-compile (require 'project)) (declare-function ansi-color-apply-on-region "ansi-color") (declare-function dirvish-fd-find "dirvish-fd") (declare-function dirvish-tramp-noselect "dirvish-tramp") -(declare-function project-root "project") ;;;; User Options @@ -279,7 +278,7 @@ input for `dirvish-redisplay-debounce' seconds." (defvar dirvish--selected-window nil) (defvar dirvish--mode-line-fmt nil) (defvar dirvish--header-line-fmt nil) -(defvar dirvish--session-hash (make-hash-table)) +(defvar dirvish--session-hash (make-hash-table :test #'equal)) (defvar dirvish--parent-hash (make-hash-table :test #'equal)) (defvar dirvish--available-attrs '()) (defvar dirvish--available-preview-dispatchers '()) @@ -363,7 +362,7 @@ DOCSTRING is the docstring for the attribute. An optional "Get FILE's ATTRIBUTE from `dirvish--attrs-hash'. When the attribute does not exist, set it with BODY." (declare (indent defun)) - `(let* ((md5 (intern (secure-hash 'md5 ,file))) + `(let* ((md5 (secure-hash 'md5 ,file)) (hash (gethash md5 dirvish--attrs-hash)) (cached (plist-get hash ,attribute)) (attr (or cached ,@body))) @@ -462,11 +461,6 @@ ALIST is window arguments passed to `window--display-buffer'." (let ((dv (or dv (dirvish-curr)))) (eq (dv-root-window dv) dirvish--selected-window))) -(defun dirvish--get-scope () - "Return computed scope according to `dirvish-scopes'." - (cl-loop for (k v) on dirvish-scopes by 'cddr - append (list k (and (functionp v) (funcall v))))) - (defun dirvish--format-menu-heading (title &optional note) "Format TITLE as a menu heading. When NOTE is non-nil, append it the next line." @@ -482,7 +476,7 @@ When NOTE is non-nil, append it the next line." "Return session DV's utility buffer of TYPE (defaults to `temp'). If NO-CREATE is non-nil, do not create the buffer. If INHIBIT-HIDING is non-nil, do not hide the buffer." - (let* ((id (if dv (format "-%s*" (dv-name dv)) "*")) + (let* ((id (if dv (format "-%s*" (dv-id dv)) "*")) (name (format "%s*Dirvish-%s%s" (if inhibit-hiding "" " ") type id))) (if no-create (get-buffer name) (get-buffer-create name)))) @@ -502,24 +496,22 @@ Set process's SENTINEL and PUTS accordingly." (cl-defstruct (dirvish (:conc-name dv-)) "Define dirvish session (`DV' for short) struct." - (type () :documentation "is the type of DV.") - (root-window () :documentation "is the root/main window of DV.") - (dedicated () :documentation "passes to `set-window-dedicated-p' for ROOT-WINDOW.") - (size-fixed () :documentation "passes to `window-size-fixed' for ROOT-WINDOW.") - (root-window-fn () :documentation "is a function used to create the ROOT-WINDOW for DV.") - (open-file-fn () :documentation "is a function used to open file under the cursor.") - (curr-layout () :documentation "is the working layout recipe of DV.") - (ff-layout - dirvish-default-layout :documentation "is a full-frame layout recipe.") - (reuse () :documentation "indicates if DV has been reused.") - (ls-switches - dired-listing-switches :documentation "is the directory listing switches.") - (preview-buffers () :documentation "holds all file preview buffers of DV.") - (preview-window () :documentation "is the window to display preview buffer.") - (name (cl-gensym) :documentation "is an unique symbol to identify DV.") - (winconf () :documentation "is a saved window configuration.") - (index () :documentation "is the current (cwd-str . buffer-obj) cons within ROOT-WINDOW.") - (roots () :documentation "is all the history INDEX entries in DV.")) + (id (format-time-string "%D|%T") :documentation "is the created time stamp of DV, used as its unique id.") + (type () :documentation "is the type of DV.") + (root-window () :documentation "is the root/main window of DV.") + (dedicated () :documentation "passes to `set-window-dedicated-p' for ROOT-WINDOW.") + (size-fixed () :documentation "passes to `window-size-fixed' for ROOT-WINDOW.") + (root-window-fn () :documentation "is a function used to create the ROOT-WINDOW for DV.") + (open-file-fn () :documentation "is a function used to open file under the cursor.") + (curr-layout () :documentation "is the working layout recipe of DV.") + (ff-layout dirvish-default-layout :documentation "is a full-frame layout recipe.") + (reuse () :documentation "indicates if DV has been reused.") + (ls-switches dired-listing-switches :documentation "is the directory listing switches.") + (preview-buffers () :documentation "holds all file preview buffers of DV.") + (preview-window () :documentation "is the window to display preview buffer.") + (winconf () :documentation "is a saved window configuration.") + (index () :documentation "is the current (cwd-str . buffer-obj) cons within ROOT-WINDOW.") + (roots () :documentation "is all the history INDEX entries in DV.")) (defun dirvish--new (&rest args) "Create and save a new dirvish struct to `dirvish--session-hash'. @@ -527,28 +519,25 @@ ARGS is a list of keyword arguments for `dirvish' struct." (let (slots new) (while (keywordp (car args)) (dotimes (_ 2) (push (pop args) slots))) (setq new (apply #'make-dirvish (reverse slots))) - (puthash (dv-name new) new dirvish--session-hash) + (puthash (dv-id new) new dirvish--session-hash) (dirvish--check-deps) (dirvish--create-root-window new) new)) (defun dirvish--get-session (&optional key val) "Return the first matched session has KEY of VAL." - (cl-loop with scope = (dirvish--get-scope) - with fn = (and key (intern (format "dv-%s" key))) - for dv in (hash-table-values dirvish--session-hash) - for idx = (cdr (dv-index dv)) for live? = (buffer-live-p idx) - for tab = (and live? (with-current-buffer idx (dirvish-prop :tab))) - for frame = (and live? (with-current-buffer idx (dirvish-prop :frame))) - for persp = (and live? (with-current-buffer idx (dirvish-prop :persp))) - when (or (not live?) ; newly created session - (and (equal tab (plist-get scope :tab)) - (equal frame (plist-get scope :frame)) - (equal persp (plist-get scope :persp)) - (let ((res (and fn (funcall fn dv)))) - (cond ((not fn) t) - ((eq key 'roots) - (memq val (mapcar #'cdr res))) - (res (eq val res)))))) + (cl-loop for dv being the hash-values of dirvish--session-hash + for b = (cdr (dv-index dv)) when (not (buffer-live-p b)) return dv + with (fr tab psp) = (cl-loop for (_ v) on dirvish-scopes by 'cddr + collect (and (functionp v) (funcall v))) + when (and (eq (with-current-buffer b (dirvish-prop :tab)) tab) + (eq (with-current-buffer b (dirvish-prop :frame)) fr) + (eq (with-current-buffer b (dirvish-prop :persp)) psp) + (let* ((fn (and key (intern (format "dv-%s" key)))) + (res (and fn (funcall fn dv)))) + (cond ((not fn) t) + ((eq key 'roots) + (memq val (mapcar #'cdr res))) + (res (eq val res))))) return dv)) (defun dirvish--clear-session (dv) @@ -565,7 +554,7 @@ ARGS is a list of keyword arguments for `dirvish' struct." (when-let* ((wconf (dv-winconf dv))) (set-window-configuration wconf))) (mapc #'dirvish--kill-buffer (dv-preview-buffers dv)) (cl-loop for b in (buffer-list) for bn = (buffer-name b) when - (string-match-p (format " ?\\*Dirvish-.*-%s\\*" (dv-name dv)) bn) + (string-match-p (format " ?\\*Dirvish-.*-%s\\*" (dv-id dv)) bn) do (dirvish--kill-buffer b)) (setq dirvish--parent-hash (make-hash-table :test #'equal)) (cond (dirvish-reuse-session (setf (dv-winconf dv) nil)) @@ -781,7 +770,7 @@ buffer, it defaults to filename under the cursor when it is nil." ((eq dired-auto-revert-buffer t) (revert-buffer)) ((functionp dired-auto-revert-buffer) (when (funcall dired-auto-revert-buffer dir) (revert-buffer)))) - (dirvish-prop :dv (dv-name dv)) + (dirvish-prop :dv (dv-id dv)) (dirvish-prop :gui (display-graphic-p)) (dirvish-prop :remote remote) (dirvish-prop :root key) @@ -842,9 +831,9 @@ When FORCE, ensure the preview get refreshed." (wconf (dv-winconf dv)) ((eq buf (window-buffer (selected-window))))) (set-window-configuration wconf)) - (remhash (dv-name dv) dirvish--session-hash) + (remhash (dv-id dv) dirvish--session-hash) (cl-loop for b in (buffer-list) for bn = (buffer-name b) when - (string-match-p (format " ?\\*Dirvish-.*-%s\\*" (dv-name dv)) bn) + (string-match-p (format " ?\\*Dirvish-.*-%s\\*" (dv-id dv)) bn) do (dirvish--kill-buffer b))))) (defun dirvish-selection-change-h (&rest _) @@ -862,7 +851,9 @@ When FORCE, ensure the preview get refreshed." (winconf t) (layout t) (old-tab (with-selected-window window (dirvish-prop :tab))) (old-frame (with-selected-window window (dirvish-prop :frame))) - (sc (dirvish--get-scope)) (frame t) (tab t)) + (sc (cl-loop for (k v) on dirvish-scopes by 'cddr + append (list k (and (functionp v) (funcall v))))) + (frame t) (tab t)) (setq winconf (dv-winconf dv) layout (dv-curr-layout dv) frame (plist-get sc :frame) tab (plist-get sc :tab)) (when (and (dv-reuse dv) (not (equal old-frame frame))) @@ -1155,7 +1146,7 @@ Dirvish sets `revert-buffer-function' to this function." (dired-revert) (dirvish--hide-dired-header) (when ignore-auto ; meaning it is called interactively from user - (setq-local dirvish--attrs-hash (make-hash-table)) + (setq-local dirvish--attrs-hash (make-hash-table :test #'equal)) (dirvish--dir-data-async default-directory (current-buffer))) (run-hooks 'dirvish-after-revert-hook)) @@ -1166,7 +1157,8 @@ Dirvish sets `revert-buffer-function' to this function." (use-local-map dirvish-mode-map) (dirvish--hide-dired-header) (dirvish--maybe-toggle-cursor 'box) ; restore from `wdired' - (setq-local dirvish--attrs-hash (or dirvish--attrs-hash (make-hash-table)) + (setq-local dirvish--attrs-hash + (or dirvish--attrs-hash (make-hash-table :test #'equal)) revert-buffer-function #'dirvish-revert tab-bar-new-tab-choice "*scratch*" dired-hide-details-hide-symlink-targets nil @@ -1193,7 +1185,7 @@ LEVEL is the depth of current window." ((memq 'vscode-icon dirvish-attributes) '(vscode-icon)))))) (with-current-buffer buf (dirvish-directory-view-mode) - (dirvish-prop :dv (dv-name dv)) + (dirvish-prop :dv (dv-id dv)) (dirvish-prop :remote (file-remote-p dir)) (puthash dir str dirvish--parent-hash) (erase-buffer) @@ -1205,7 +1197,7 @@ LEVEL is the depth of current window." (font-lock-mode 1) (dired-goto-file-1 (file-name-nondirectory index) index (point-max)) (dirvish--maybe-toggle-cursor '(box . 0)) ; always hide cursor in parents - (setq-local dirvish--attrs-hash (make-hash-table) + (setq-local dirvish--attrs-hash (make-hash-table :test #'equal) dirvish--working-attrs (dirvish--attrs-expand attrs)) (dirvish--render-attrs) buf))) @@ -1247,11 +1239,11 @@ LEVEL is the depth of current window." (fundamental-mode) (setq mode-line-format nil header-line-format nil) (add-hook 'window-scroll-functions #'dirvish-apply-ansicolor-h nil t)) (with-current-buffer (dirvish--util-buffer 'header dv) - (dirvish-prop :dv (dv-name dv)) + (dirvish-prop :dv (dv-id dv)) (setq cursor-type nil window-size-fixed 'height mode-line-format nil header-line-format nil)) (with-current-buffer (dirvish--util-buffer 'footer dv) - (dirvish-prop :dv (dv-name dv)) + (dirvish-prop :dv (dv-id dv)) (setq cursor-type nil window-size-fixed 'height mode-line-format nil header-line-format nil))) @@ -1268,8 +1260,7 @@ INHIBIT-SETUP is passed to `dirvish-data-for-dir'." (cond ((eq t tp) (setq tp '(dir . nil))) (tp (setq tp `(,(if (file-directory-p tp) 'dir 'file) . ,tp))) (t (setq tp '(file . nil)))) - (puthash (intern (secure-hash 'md5 file)) - `(:builtin ,attrs :type ,tp) hs))) + (puthash (secure-hash 'md5 file) `(:builtin ,attrs :type ,tp) hs))) (cons bk hs))) (lambda (p _) (pcase-let ((`(,buf . ,inhibit-setup) (process-get p 'meta)) diff --git a/extensions/dirvish-fd.el b/extensions/dirvish-fd.el index 423cf846ec..51c707f4ec 100644 --- a/extensions/dirvish-fd.el +++ b/extensions/dirvish-fd.el @@ -97,7 +97,7 @@ Raise an error if fd executable is not available." "Return fd buffer name of DV with user INPUT at DIR." (format dirvish-fd-bufname (or input "") (file-name-nondirectory (directory-file-name dir)) - (dv-name dv))) + (dv-id dv))) (defun dirvish-fd--apply-switches () "Apply fd SWITCHES to current buffer." @@ -435,7 +435,7 @@ The command run is essentially: (set-keymap-parent map (current-local-map)) (define-key map "\C-c\C-k" #'dirvish-fd-kill) (use-local-map map)) - (dirvish-prop :dv (dv-name dv)) + (dirvish-prop :dv (dv-id dv)) (dirvish-prop :gui (display-graphic-p)) (dirvish-prop :fd-switches fd-switches) (dirvish-prop :cus-header 'dirvish-fd-header) diff --git a/extensions/dirvish-peek.el b/extensions/dirvish-peek.el index 9441e0495c..02e898c721 100644 --- a/extensions/dirvish-peek.el +++ b/extensions/dirvish-peek.el @@ -73,7 +73,7 @@ one of categories in `dirvish-peek-categories'." (setf (dv-index new-dv) (cons default-directory (current-buffer))) (setf (dv-preview-window new-dv) (or (minibuffer-selected-window) (next-window))) - (dirvish-prop :dv (dv-name new-dv))))) + (dirvish-prop :dv (dv-id new-dv))))) (defun dirvish-peek-update-h () "Hook for `post-command-hook' to update peek window." @@ -100,7 +100,7 @@ one of categories in `dirvish-peek-categories'." (dolist (dv (hash-table-values dirvish--session-hash)) (when (eq (dv-type dv) 'peek) (dirvish--clear-session dv) - (remhash (dv-name dv) dirvish--session-hash))) + (remhash (dv-id dv) dirvish--session-hash))) (dirvish-prop :peek-last nil)) ;;;###autoload diff --git a/extensions/dirvish-vc.el b/extensions/dirvish-vc.el index bb702e57d1..3b5bc3159e 100644 --- a/extensions/dirvish-vc.el +++ b/extensions/dirvish-vc.el @@ -119,7 +119,7 @@ It is called when `:vc-backend' is included in DIRVISH-PROPs while (shell-command-to-string (format "git log -1 --pretty=%%s %s" (shell-quote-argument file)))))) - (puthash (intern (secure-hash 'md5 file)) + (puthash (secure-hash 'md5 file) `(:vc-state ,state :git-msg ,msg) hs))) hs)) (lambda (p _)