0

When visiting a folder with emacsclient, for example through emacsclient ., using dired, opening a folder using a will cause emacsclient to terminate. I believe this is because a, bound to dired-find-alternate-file will close the buffer emacsclient is in some way bound to causing it to terminate. I observe the same behavior when using dired-single.el.

Is there any way to prevent this from happening? Given my above assumptions about how why this happens: to make dired reuse the same buffer rather than destroy it?

2
  • dired-find-alternate-file's doc string says: In Dired, visit file or directory on current line via ‘find-alternate-file’. This kills the Dired buffer, then visits the current line’s file or directory. So it seems to me that the only way to avoid the problem is to avoid using dired-find-alternate-file. What's wrong with dired-find-file (bound to f)? It leaves the directory buffer alone, so emacsclient can continue enjoying its existence.
    – NickD
    Commented Jul 9, 2020 at 8:18
  • I would prefer to not fill upp my buffer list with a lot of dired buffers I will never use again.
    – Rovanion
    Commented Jul 9, 2020 at 8:21

2 Answers 2

1

You could remap dired-find-alternate-file to a custom command which firstly checks to see whether server-buffer-clients is non-nil in that dired buffer. If it's nil then just go ahead and call dired-find-alternate-file; if it's set, then work around the issue...

Some possible workarounds are:

  1. Call dired-find-file instead of dired-find-alternate-file. Maybe bury-buffer for the original buffer, too.

  2. Set the buffer-local server-buffer-clients to nil. This will prevent server-kill-buffer from killing every client for which this was the sole remaining buffer of interest. It means there will be a stale entry in the buffers list for the client process -- but server-buffer-done already copes with dead buffers, so it's basically fine.

    Or similar: remove the buffer-local kill-buffer-hook entry server-kill-buffer in that buffer.

    Either way, when the dired buffer is killed, the client stays alive.

    That sounds good, but probably isn't actually sufficient. In the case you're interested in -- the one where that client in reality has no live buffers of interest after that dired buffer has been killed -- then that client is going to be killed the next time that any client-buffer (for any client) is killed -- so you might still lose the client without meaning to.

  3. That all being the case, I think instead of using (2), your custom command would be better to call server-visit-files for the file you're asking dired to open, in order that the new buffer can be registered for the client (in practice you probably need to do this for every client which was interested in the original buffer). Then you're effectively shifting the client's interest from buffer to buffer, but it's not subject to sudden death on account of some other client.

1

This is an old question, but as this annoyance is not going away, I thought people might appreciate a code solution. My approach is to write alternatives to find-alternate-file and dired-find-alternate-file.

(defun my-find-alternate-file (newfile)
  "switch to new file, then kill old buffer"
  (remove-hook 'kill-buffer-hook 'server-kill-buffer t)
  (let ((my-old-buffer (current-buffer)))
    (find-file newfile)
    (kill-buffer my-old-buffer)))

(defun my-dired-find-alternate-file ()
  "open a new file from dired, then kill the old dired buffer"
  (interactive)
  (my-find-alternate-file (dired-get-file-for-visit)))

Uses @phils second approach and seems to be working for me.

=== edit ===

By the way, as of 28 you are supposed to be able to set dired-kill-when-opening-new-dired-buffer to get this same effect, but it only seems to works intermittently--most of the time you end up with an ever-expanding list of dired buffers.

7
  • @phils Thanks. This was actually a simplification of my real function (which also tracks the position you were at in the previous buffer) and I didn't test. I tried the current version and it should be ok. Sorry about that.
    – farnsy
    Commented Sep 11, 2022 at 5:36
  • I would M-x report-emacs-bug if dired-kill-when-opening-new-dired-buffer is not working as advertised (and, ideally, you can suggest a way to reproduce the issue from emacs -Q).
    – phils
    Commented Sep 13, 2022 at 1:31
  • (interactive) with no args doesn't mesh with having a required arg (newfile) for interactive use. You could make the argument optional and use (call-interactively 'find-file) instead of (find-file newfile) if it wasn't supplied. Alternatively, if you only expect to use my-dired-find-alternate-file then my-find-alternate-file needn't be interactive at all.
    – phils
    Commented Sep 13, 2022 at 1:37
  • @phils Thanks. I'll take a look. I'm new to elisp...lots to learn. I'm not 100% clear on when functions need to be marked as interactive. A lambda with (my-find-alternate-file "..") is bound to h in my setup, so thought I needed it, but I just tried without and it worked. Lots to learn.
    – farnsy
    Commented Sep 13, 2022 at 3:29
  • In that instance your lambda function presumably includes (interactive)? It is only necessary for the function which is being bound to the key sequence to be interactive (otherwise more or less every function would need to be interactive).
    – phils
    Commented Sep 13, 2022 at 4:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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