2

I'm trying to programmatically define the windows in my frame. I have 4 windows, two with dired buffers in them so that I can select the file I want to visit.

(delete-other-windows)
(split-window-horizontally)
(dired ".")
(split-window-vertically)
(find-file "test.txt")
(other-window -1)
(split-window-vertically)
(dired ".")
(other-window -1)
+-----------+-----------+
|           |           |
|           |           |
|  test.txt |   dired   |
|           |           |
|           |           |
+-----------+-----------+
|           |           |
|   dired   | whatever  |
|           |           |
|           |           |
+-----------+-----------+

To open a file in the current dired buffer, I set (put 'dired-find-alternate-file 'disabled nil) to disable the warning and select the file I want with a (dired-find-alternate-file). When I do this, however, it kills the other dired buffer I have open. It seems that dired can only have one buffer per directory.

How can I have two dired buffers for the same directory, but kill each of them independently?

edit

Using indirect buffers, I can get what I want, but it ain't pretty. Good gravy, is there a better way?

(defun my-clone-indirect-buffer-same-window (newname display-flag &optional norecord)
  "A copy-paste of clone-indirect-buffer, but with pop-to-buffer
changed to pop-to-buffer-same-window."
  (interactive
   (progn
     (if (get major-mode 'no-clone-indirect)
     (error "Cannot indirectly clone a buffer in %s mode" mode-name))
     (list (if current-prefix-arg
           (read-buffer "Name of indirect buffer: " (current-buffer)))
       t)))
  (if (get major-mode 'no-clone-indirect)
      (error "Cannot indirectly clone a buffer in %s mode" mode-name))
  (setq newname (or newname (buffer-name)))
  (if (string-match "<[0-9]+>\\'" newname)
      (setq newname (substring newname 0 (match-beginning 0))))
  (let* ((name (generate-new-buffer-name newname))
     (buffer (make-indirect-buffer (current-buffer) name t)))
    (with-current-buffer buffer
      (run-hooks 'clone-indirect-buffer-hook))
    (when display-flag
      (pop-to-buffer-same-window buffer norecord))
    buffer))

(delete-other-windows)
(split-window-horizontally)
(dired ".")
(split-window-vertically)
(find-file "test.txt")
(other-window -1)
(split-window-vertically)
(switch-to-buffer (cdr (car dired-buffers)))
(my-clone-indirect-buffer-same-window nil t)
(other-window -1) 

edit2

Based on Drew's answer, the following does what I asked:

(setq my-root ".")
(setq my-main "test.txt")

(delete-other-windows)
(split-window-horizontally)
(dired my-root)
(split-window-vertically)
(find-file my-main)
(other-window -1)
(split-window-vertically)

;; creates a new buffer with same name as my-root containing 
;; a snapshot of the file listing
(dired (cons my-root (directory-files my-root)))
(other-window -1)
5
  • I don't get the behavior you describe. C-u M-x dired RET RET asks about ls flags, but the buffer it creates is not independent: if I kill it, any other dired buffer for the same directory also disappears. You can create indirect buffers but AFAIK, there is a single buffer for any one file or directory, so when that buffer is killed, it disappears from all windows that display it.
    – NickD
    Dec 9, 2021 at 16:18
  • @NickD, yes, you are correct. I had that wrong. I must have been in a different directory. I will remove that from the question. Dec 9, 2021 at 16:34
  • 1
    Have you looked at indirect buffers? Within emacs, you can get to that section with C-h i g(elisp)indirect buffers.
    – NickD
    Dec 9, 2021 at 16:43
  • With respect to the notion that "It seems that dired can only have one buffer per directory," perhaps you can programmatically create a new buffer with a different name (but populate the buffer with the same directory as another buffer that already exists). You can set up a simple naming convention that just adds a consecutive number to the name of the buffer containing the same directory as other buffers; e.g., "*foo*", "*foo<01>*", "*foo<02>*". That way, there would be no need for an indirect buffer. [PS: You can programmatically create new windows above, below, left, right.]
    – lawlist
    Dec 9, 2021 at 18:28
  • @lawlist: I don't think that works. I can rename the buffers, but when I kill one, they all go ("all" = two in this case, so I'm extrapolatiing...)
    – NickD
    Dec 9, 2021 at 19:11

1 Answer 1

1

You can create additional buffers that Dired the same directory, but with this caveat: those additional buffers are in fact Dired listings of a particular set of files (and subdirs etc.), which you specify when you create the buffers.

So changing the set of files in the directory does not change the set of files listed in the Dired listing of such an additional buffer for that directory.

To create such a Dired buffer other-DIR, given that you already have a Dired buffer named DIR (where DIR is the directory name), do this:

M-: (dired (cons "other-DIR" (directory-files "DIR")))

This gives you a separate Dired buffer, but its set of files is defined when you create the buffer. You can of course also specify particular ls switches etc.

With this technique you can create Dired buffers listing any set of files and subdirs - they need not even be in the same directory tree. In this particular case (above), the arbitrary set of files happen to be the files in the given directory (obtained with directory-files) at the time the buffer is created.

See the doc of command dired for more info.


Library Dired+ offers more flexibility for using such Dired buffers that list an arbitrary set of files.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.