Skip to content

Instantly share code, notes, and snippets.

@mjkramer
Last active March 21, 2018 01:39
Show Gist options
  • Save mjkramer/1bddf7dca70908862758eb833c43b3bc to your computer and use it in GitHub Desktop.
Save mjkramer/1bddf7dca70908862758eb833c43b3bc to your computer and use it in GitHub Desktop.
fewer dired buffers, for your health!
(with-eval-after-load 'dired
(substitute-key-definition 'dired-find-file 'my/diredp-find-file-reuse-dir-buffer dired-mode-map)
(substitute-key-definition 'dired-mouse-find-file 'my/diredp-mouse-find-file-reuse-dir-buffer dired-mode-map)
(substitute-key-definition 'dired-up-directory 'my/diredp-up-directory-reuse-dir-buffer dired-mode-map))
(defun my/diredp-find-file-reuse-dir-buffer () ; Not bound
"Like `dired-find-file', but reuse Dired buffers.
Unlike `dired-find-alternate-file' this does not use
`find-alternate-file' unless (1) the target is a directory that is not
yet visited as a Dired buffer, and (2) the current (Dired) buffer is
not visited also in some other window (possibly in an iconified
frame)."
(interactive)
(set-buffer-modified-p nil)
(let ((file (dired-get-file-for-visit)))
(my/diredp--reuse-dir-buffer-helper file)))
(defun my/diredp-mouse-find-file-reuse-dir-buffer (event &optional find-file-func find-dir-func) ; Not bound
"Like `dired-mouse-find-file', but reuse Dired buffers.
Unlike `dired-find-alternate-file' this does not use
`find-alternate-file' unless (1) the target is a directory that is not
yet visited as a Dired buffer, and (2) the current (Dired) buffer is
not visited also in some other window (possibly in an iconified
frame).
Non-nil optional args FIND-FILE-FUNC and FIND-DIR-FUNC specify
functions to visit the file and directory, respectively.
Defaults: `find-file' and `dired', respectively."
(interactive "e")
(let (window pos file)
(save-excursion
(setq window (posn-window (event-end event))
pos (posn-point (event-end event)))
(unless (windowp window) (error "No file chosen"))
(set-buffer (window-buffer window))
(goto-char pos)
(setq file (dired-get-file-for-visit)))
(select-window window)
(my/diredp--reuse-dir-buffer-helper file find-file-func find-dir-func)))
(defun my/diredp-up-directory-reuse-dir-buffer (&optional other-window) ; Not bound
"Like `diredp-up-directory', but reuse Dired buffers.
With a prefix arg, Dired the parent directory in another window.
On MS Windows, moving up from a root Dired buffer does not kill that
buffer (the Windows drives buffer is not really a Dired buffer)."
(interactive "P")
(let* ((dir (dired-current-directory))
(dirfile (directory-file-name dir))
(up (file-name-directory dirfile)))
(or (dired-goto-file dirfile)
;; Only try `dired-goto-subdir' if buffer has more than one dir.
(and (cdr dired-subdir-alist) (dired-goto-subdir up)) ; It is a subdir inserted in current Dired.
(progn (my/diredp--reuse-dir-buffer-helper up nil nil other-window)
(dired-goto-file dir))
(and (memq system-type '(windows-nt ms-dos)) (diredp-w32-drives other-window)))))
(defun my/diredp--reuse-dir-buffer-helper (file &optional find-file-func find-dir-func other-window)
"Helper for commands `diredp-*-reuse-dir-buffer' commands.
Non-nil optional args FIND-FILE-FUNC and FIND-DIR-FUNC specify
functions to visit the file and directory, respectively.
Defaults: `find-file' and `dired', respectively.
Unlike `dired-find-alternate-file' this does not use
`find-alternate-file' unless (1) the target is a directory that is not
yet visited as a Dired buffer, and (2) the current (Dired) buffer is
not visited also in some other window (possibly in an iconified
frame)."
(setq find-file-func (or find-file-func (if other-window #'find-file-other-window #'find-file))
find-dir-func (or find-dir-func (if other-window #'dired-other-window #'dired)))
(let (;; This binding prevents problems with preserving point in windows displaying Dired buffers, because
;; reverting a Dired buffer empties it, which changes the places where the markers used by
;; `switch-to-buffer-preserve-window-point' point.
(switch-to-buffer-preserve-window-point (and (boundp 'switch-to-buffer-preserve-window-point) ; Emacs 24+
(or (not (boundp 'dired-auto-revert-buffer))
(not dired-auto-revert-buffer))
switch-to-buffer-preserve-window-point))
(find-file-run-dired t)
(wins ())
(alt-find-file-func (if other-window
#'find-alternate-file-other-window
#'find-alternate-file))
dir-bufs)
(if (or (not (file-directory-p file)) ; New is a not a directory
(dired-buffers-for-dir file) ; or there is a Dired buffer for it, even as a subdir.
(and (setq dir-bufs (dired-buffers-for-dir default-directory)) ; Dired bufs for current (old).
(progn
(dolist (buf dir-bufs)
(setq wins (append wins (get-buffer-window-list buf 'NOMINI 0))))
(setq wins (delq nil wins))
(cdr wins)))) ; More than one window showing current Dired buffer.
(if (file-directory-p file)
(or (and (cdr dired-subdir-alist) (dired-goto-subdir file)) ; New is a subdir inserted in current
(funcall find-dir-func file))
(funcall find-file-func (file-name-sans-versions file t)))
(funcall alt-find-file-func (file-name-sans-versions file t)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment