0

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).

tbrodbeck
  • 177
  • 1
  • 10

1 Answers1

1

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)))
  win)
  1. You do actually not need get-file-buffer just use find-file-other-frame instead. It should do everything you need.

EDIT:

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
      (progn
        (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\")"
Tobias
  • 32,569
  • 1
  • 34
  • 75
  • 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. – tbrodbeck Jun 24 '19 at 08:00
  • Okay got it to work piping them together like this: `emacsclient -e "(get-buffer-window (get-file-buffer \".spacemacs\"))"` Thanks a lot! – tbrodbeck Jun 24 '19 at 08: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 08: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. – tbrodbeck Jun 24 '19 at 08:28
  • Okay got it like this: ```emacsclient -e "(get-buffer-window (get-file-buffer \"$1\") 'visible)``` – tbrodbeck Jun 24 '19 at 08:33
  • @Tillus Could you try my second proposal in the EDIT? – Tobias Jun 24 '19 at 09:10
  • @Tillus Do not forget to eval the code in your server. For a test you can just eval the defun in your init file. Later when you restart the Emacs that runs the server the defun is evaluated in the initialization phase. – Tobias Jun 24 '19 at 09:17
  • Oh sorry, maybe I was not clear enough: `emacsclient -e "(get-buffer-window (get-file-buffer \"$1\") 'visible)` already works :). i use it like this (pseudocode): `[[ emacsclient -e "(get-buffer-window (get-file-buffer \"$1\") 'visible) == "nil"]] `focus the visible buffer, else create new frame $1. But I am sure your solution works as well – tbrodbeck Jun 24 '19 at 10:12