0

How do I open a file foo, associated with a major mode (in this case python, so it's a foo.py), on the right side of a split window (and the window is split only for this major mode)? The following code doesn't work at all (it displays the scratch buffer on both sides).

(defun my-eval-after-load-python()
  (split-window-horizontally)
)
(eval-after-load "python" '(my-eval-after-load-python))
Drew
  • 29,895
  • 7
  • 74
  • 104
Allan Felipe
  • 201
  • 2
  • 8

1 Answers1

1

For setting up a particular major-mode that matches a file name or file extension, see the variable auto-mode-alist. Emacs 25 supports python-mode for .py file extensions out-of-the-box.

Caveat re Startup:  The built-in (hard-coded) library startup.el contains some selection of buffers/windows that are displayed on startup. Customizing a particular window layout upon starting Emacs is always somewhat of a challenge, and the method will most likely be custom to a particular user. For better results, the user may wish to place the window organization functions at the very bottom of the .emacs or init.el or use the emacs-startup-hook (which runs towards the end of the startup process). Certain libraries such as desktop.el (desktop restore) will complicate the selection of which buffer should have focus when startup finishes. Each user will need to invest some time organizing the startup in a way that suits his/her needs. For example, there may be two windows and the user may want to have focus in the other -- something lo-tech like (other-window 1) at the bottom of the customization file might be all that is needed. In the example below with my-display-buffer, the value returned is a window -- the user may wish to wrap the last line window like this (select-window window) so that it gets selected; or, instead of modifying my-display-buffer, the user could add (select-window (my-display-buffer BUFFER ALIST DIRECTION)) when using the function without modifying it internally. The original poster may also be interested in using find-file (to target the current window), or find-file-other-window (to create/target another window) -- e.g., (find-file-other-window "~/foo.py").

If focus is already in the desired window (e.g., the window on the right is already selected), then just use something like set-window-buffer or switch-to-buffer.

To control display of a buffer above, below, left or right, see the following example that uses a custom function called my-display-buffer hereinbelow:

Sample Usage:  The function definition of my-display-buffer would need to appear in the .emacs or init.el file prior to using any of these four sample snippets.

(let ((buffer (find-file-noselect "~/foo.py")))
  (with-current-buffer buffer
    (message "major-mode:  %s" major-mode))
  (my-display-buffer buffer nil 'left))

or

(let ((buffer (find-file-noselect "~/foo.py")))
  (with-current-buffer buffer
    (message "major-mode:  %s" major-mode))
  (my-display-buffer buffer nil 'right))

or

(let ((buffer (find-file-noselect "~/foo.py")))
  (with-current-buffer buffer
    (message "major-mode:  %s" major-mode))
  (my-display-buffer buffer nil 'above))

or

(let ((buffer (find-file-noselect "~/foo.py")))
  (with-current-buffer buffer
    (message "major-mode:  %s" major-mode))
  (my-display-buffer buffer nil 'below))

Example Function:

(defun my-display-buffer (buffer alist direction &optional size pixelwise)
"BUFFER:  The buffer that will be displayed.
ALIST:  See the doc-string of `display-buffer' for more information.
DIRECTION:  Must use one of these symbols:  'left 'right 'below 'above
SIZE:  See the doc-string for `split-window'.
PIXELWISE:  See the doc-string for `split-window'.
There are three possibilities:
-  (1) If a window on the frame already displays the target buffer,
then just reuse the same window.
-  (2) If there is already a window in the specified direction in relation
to the selected window, then display the target buffer in said window.
-  (3) If there is no window in the specified direction, then create one
in that direction and display the target buffer in said window."
  (let ((window
          (cond
            ((get-buffer-window buffer (selected-frame)))
            ((window-in-direction direction))
            (t
              (split-window (selected-window) size direction pixelwise)))))
    (window--display-buffer buffer window 'window alist display-buffer-mark-dedicated)
    window))
lawlist
  • 13,099
  • 3
  • 49
  • 158
  • Thanks, it seems it works perfectly. I want the focus on the newly created window, so the select-window idea will be used. There's just one thing I wasn't clear about. The file is opened/created originally from a terminal, like: emacs foo.py, so its name is not stated explicitly in the code (the .emacs), how is that done? – Allan Felipe Dec 12 '16 at 23:54
  • 1
    The following example assumes `my-display-buffer` is somewhere inside the `.emacs` file and the following command line is called from a terminal: `emacs -nw --eval="(let ((buffer (find-file-noselect \"~/foo.py\"))) (my-display-buffer buffer nil 'right))"` If I were going to be doing a lot of these, I would set up function inside the `.emacs` file to simply matters. – lawlist Dec 13 '16 at 02:58
  • Great, it works as expected! It will be done a lot, how would that function be defined? Some function inside the defun would read the name given by the shell? I thought I'd be able to simply type "emacs file.py", I hope it's possible ;( (Also, I'm curious about the reason you set up the terminal mode -nw) – Allan Felipe Dec 13 '16 at 21:25
  • The version of Emacs that I use is both the GUI version and the terminal version (combined into one); and, the `-nw` is what tells Emacs to not launch the GUI version -- i.e., without using `-nw`, the GUI version is launched. Off the top of my head, I do not know how to simplify the example to `emacs file.py` from the terminal. I could simplify it to `emacs -nw --eval="(my-func \"foo.py\")"` but that's as far as I could go based on my current level of Emacs-fu. – lawlist Dec 14 '16 at 05:55
  • It seems that simply `(my-display-buffer (current-buffer) alist direction)` inside my eval function does the trick. – Allan Felipe Dec 15 '16 at 05:27
  • 1
    The file to study is `startup.el` -- e.g., the incoming command-line arguments are recorded/set to the variable `command-line-args` and the `.emacs` that loads can access those arguments. There are so many variations/possibilities in terms of command line arguments, and so many endless possibilities of what a user may have inside his/her user-configuration files, it is difficult/impossible to come up with a guaranteed solution that will work in all cases. In the end, whatever you decide upon will likely be unique to your own setup. – lawlist Dec 15 '16 at 05:34