I want to implement a script that I can call from my file explorer to be able to open a new frame with the chosen file (emacsclient -nc $1), but only if the file does not already exist then I simply want to focus the right frame (or buffer). So how to I find out if a frame is already visible?

So far I tried to use this function get-buffer-window(How to know my buffer's visible/focused status?) and call it with emacsclient -e, but I do not know what argument I should give it (I am an emacs newbie here btw :D).


The answer has two parts.

  1. The function get-file-buffer returns the buffer visiting the file given as argument or nil if there is no such buffer. You can use it in the following way:
(require 'subr-x) ;; for `when-let'
(when-let ((buf (get-file-buffer file-name))
           (win (get-buffer-window buf)))
  1. You do actually not need get-file-buffer just use find-file-other-frame instead. It should do everything you need.


Put the following into your init file:

(defun my-find-file (file)
  "Try to find FILE in a corresponding frame.
Create a new frame if it does not exist yet."
  (let* ((buf (find-file-noselect file))
         (win (get-buffer-window buf 'visible))
         (frame (and win (window-frame win))))
    (if frame
        (make-frame-visible frame)
        (raise-frame frame))
      (display-buffer-pop-up-frame buf nil))))

Therewith you only need the following line in your script file:

emacsclient -e "(my-find-file \"$1\")"
  • Hey thanks for your reply! But this is unfortunately not exactly what I am looking for. Your 1. solution returns if there is a buffer open. That's great, but it returns the buffer also if it is not visible, and I only want to know if its visible. Your 2. solution 'find-file-other-frame' basically works but has one flaw, if the file is already open in the last visited buffer, then it will open a second frame with this file. – Tillus Jun 24 '19 at 8:00
  • Okay got it to work piping them together like this: emacsclient -e "(get-buffer-window (get-file-buffer \".spacemacs\"))" Thanks a lot! – Tillus Jun 24 '19 at 8:17
  • @Tillus Your version selects the window for the current buffer if get-file-buffer returns nil. (It is not working as you want it.) See the doc for get-file-buffer. – Tobias Jun 24 '19 at 8:18
  • Yes and if it returns nil, I will open a new one. If not I will switch to the frame ``` frame=emacsclient -e "(get-buffer-window (get-file-buffer \"$1\"))" 2>/dev/null [[ "$frame" == "nil" ]] && opts='-c' # if there is no frame open create one [[ "${@/#-nw/}" == "$@" ]] && opts="$opts -n" emacsclient $opts "$1" ``` But there is another problem: get-buffer-window only returns the window if it was the last frame I focused and not if it is visible, like I want. – Tillus Jun 24 '19 at 8:28
  • Okay got it like this: emacsclient -e "(get-buffer-window (get-file-buffer \"$1\") 'visible) – Tillus Jun 24 '19 at 8:33

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.