4

With long files, I like to have two buffers that display the same file but at different positions. However, since I have two physical displays, I'd like to have two Emacs buffer, each on its own monitor, and then I could open 3, or even 4 copies of the same file! In theory...

In practice, when I try C-x 5 b or C-x 5 f, instead of opening the file / creating a new buffer with the same content in another frame, the focus goes back into original frame, original buffer...

Any thoughts?


OK, I now realized that I can create a new frame, which will then automatically show the currently selected buffer: M-xnew-frame. But what about existing frames?

  • 2
    I use a custom function with the display-buffer-alist to display buffers in select frames and select windows within those frames. For an example of how this works, check out the answer in this related thread entitled "How to intercept a file before it opens and decide which frame": stackoverflow.com/questions/18346785/… As you may already know, the buffer-list for each frame cannot be relied upon as a method for associating buffers with a frame. You may be interested in frame-bufs by Alp Aker to associate buffers. – lawlist Apr 4 '18 at 14:04
  • @lawlist thank you, I'm reading about this. – wvxvw Apr 4 '18 at 14:21
1

Have you tried C-x 5 2? It is make-frame-command that should do what you want as far as I understand.

For my needs I have created similar function to make new frame with current buffer having the same frame-width and frame-height:

(defun haba/make-new-frame ()
    (interactive)
    (make-frame `((width . ,(frame-width)) (height . ,(frame-height)))))

PS Or maybe you want smth else? Maybe you want to duplicate current frame with all windows opened there? I have read your question 4 times... :)

PS2

What I think happens

  1. You open a new frame with C-x 5 b
  2. Then you want to open another buffer in that frame and again use C-x 5 b

By default C-x 5 b will search for a buffer in list of displayed buffers in all frames and will switch to it in another existing frame instead of creating a new one.

Just use regular C-x b in a new frame:

  1. C-x 5 2 to open current buffer in a new frame
  2. C-x b to open any buffer in selected frame (in your case you are in a new frame)
  • 1
    Sorry, after asking the initial question, I realized that I can partially solve it by creating new frame with displaying the buffer I need, but if I already have one frame open, I cannot display an already existing buffer in it. – wvxvw Apr 4 '18 at 14:20
  • Still don't get it. If I open file, for example init.el then press C-x 5 2 and C-x 5 2 I get 3 frames opened with the same buffer init.el. – Maxim Kim Apr 4 '18 at 14:24
  • Still don't get it, part 2. If I open init.el then press C-x 5 2 and there C-x C-f and select file blabla.txt I will have init.el in one frame and blabla.txt in another. – Maxim Kim Apr 4 '18 at 14:27
  • @wvxvw Still don't get it, part 3. MAYBE, in a new frame you try to open buffer/file with FRAME commands (C-x 5 b). In that situation, you will be redirected to the frame that has selected buffer visible (default behaviour as far as I remember) – Maxim Kim Apr 4 '18 at 14:29
  • 2
    OK, here's the scenario: I open init.el using C-x 5 2 in a new frame. Then in the new frame I open a different file, say. .netrc, then I switch to the first frame (say, by pressing M-TAB), and then try to display .netrc in that frame. The desired effect is that .netrc is displayed in both frames, the actual effect is that the second frame gets focused and displays .netrc, while the first frame still displays init.el. – wvxvw Apr 5 '18 at 10:21
1

Here is an example using the display-buffer family of functions, based upon a more complicated example: https://stackoverflow.com/questions/18346785/how-to-intercept-a-file-before-it-opens-and-decide-which-frame . As stated in that related thread, there are several different ways to do this, including, but not limited to let-binding the display-buffer-alist. In this example, we just use the function my-frame-fn in the second argument to display-buffer. We can of course get fancy by examining all of the frame names and add a consecutive numeric digit to the frame name; or, not change the frame name at all; or ... the sky is the limit. We can also add additional frame parameters to place the top / left coordinates wherever we want. We can also adjust the frame size upon frame creation including pixelwise (https://emacs.stackexchange.com/a/17354/2287), or after the fact (https://www.gnu.org/software/emacs/manual/html_node/elisp/Size-and-Position.html). And, we could always programmatically set/select the original frame/buffer instead of the new one if we wanted to ....

I do not like to use select-frame-set-input-focus in my setup because it will cause frames on OSX to acquire focus and steal away focus from another program that I might be using; e.g., in the case of a long running Emacs function. So, instead I use the combination of select-frame and raise-frame. Please feel free to substitute select-frame for select-frame-set-input-focus and remove raise-frame if that is needed for your OS or you simply prefer it like that.

USAGE (1 of 2):  (display-buffer (current-buffer) '(my-frame-fn))

USAGE (2 of 2):  (display-buffer (find-file-noselect FILENAME) '(my-frame-fn))

(defun my-frame-fn (buffer alist)
"Display the incoming BUFFER in a frame that does not already display it.
Use up the existing frames first, before deciding to create a new frame."
  (let (target-frame)
    (catch 'break
      (dolist (the-frame (frame-list))
        (when (not (get-buffer-window buffer the-frame))
          (throw 'break
            (progn
              (setq target-frame the-frame)
              (modify-frame-parameters the-frame
                (list (cons 'name "OLD"))))))))
    (when (null target-frame)
      (setq target-frame (make-frame (list (cons 'name "NEW")))))
    (select-frame target-frame 'norecord)
    (set-window-buffer (get-largest-window) buffer)
    (select-window (get-buffer-window buffer))
    (raise-frame target-frame)))
0

Three different things come to mind, depending on just what you want. Perhaps one or more of them will help.

  1. C-x 5 2 (new frame for the current buffer).

  2. C-x 3 (or C-x 2), followed byM-x follow-mode`. But that shows the buffer in separate windows, not separate frames.

  3. Indirect buffers. Each such buffer can be dedicated to a different part of the same buffer (and those parts can overlap). See Narrow Indirect (library narrow-indirect.el).

0

It looks like you can M-x clone-indirect-buffer and then open the clone in the other frame. I haven't played with this a lot yet, but so far so good.

0

You can you C-x <LEFT> and C-x <RIGHT> to cycle among all open buffers in the current window.

It's not perfect, but it's the only way I've found to change the buffer in an existing frame to one that's open in another frame.

  • There are some interesting ideas in the other answers, I find.. – manandearth Oct 2 '18 at 14:15

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.