I'm using a fairly frame-oriented workflow (or trying to). I've run into something strange. If I write this:

(defun find-file-existing (filename)
    "Edit the existing file FILENAME.
Like \\[find-file], but only allow a file that exists, and do not allow
file names with wildcards."
    (interactive (nbutlast (find-file-read-args "Find existing file: " t)))
    (if (and (not (called-interactively-p 'interactive))
             (not (file-exists-p filename)))
        (error "%s does not exist" filename)
     (find-file-other-frame filename)

Then commands which use find-file-existing do what I want, including running the command directly from SPC SPC.

If I write this:

(defalias 'find-file 'find-file-other-frame)

Or this:

(defun find-file (filename)
    (interactive (nbutlast (find-file-read-args "Find file: " t)))
    (if (and (not (called-interactively-p 'interactive))
        (error "%s does not exist" filename)
     (find-file-other-frame filename)

Then commands which use find-file (including running it from SPC SPC) do open the file in a new frame, but also change to that buffer in the current frame.

I've been over the code quite a bit and tried a few other variants, but the code paths seem almost the same to me (just changing if there is a file-existing check or not) and it's so strange that one does something different than the other. Anyone have any ideas how this could be happening? What should I be looking for?

  • 2
    You should not, in my opinion, intertwine find-file / find-file-other-frame with defalias as they are core functions used by a zillion built-in and third-party libraries. If you want total control, I would suggest considering the usage of find-file-noselect and then target a specific frame if it exists, or create a new one if it does not ... use a custom display-buffer function ... See stackoverflow.com/q/18346785/2112489 for a working answer/example of how this might be done .... Alternatively, look for other examples customizing the display-buffer-alist.
    – lawlist
    Commented Apr 28, 2020 at 4:40
  • In the future, please indent your code conventionally. To do that, you might want to use M-x untabify before copying it in Emacs.
    – Drew
    Commented Apr 28, 2020 at 17:39

1 Answer 1


For one thing, this:

(if (and (not (called-interactively-p 'interactive))

always evaluates the first if clause after that test, since the test always evaluates to nil. That's not what you do in the first example.

(Indenting your code properly (conventionally) lets you see this kind of thing more easily.)

  • That's the intent, yes. The if is only there in order to mirror the structure of the other code to make them as similar as possible. The defalias version is of course my preferred, but I figured copying the exact code that works and making the smallest change possible was sane second attempt.
    – singpolyma
    Commented Apr 29, 2020 at 1:28

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.