euluis
euluis

Reputation: 105

How to customize Emacs split-window-X with the new window showing the next buffer?

In Emacs 21.x I don't know if via a specific customization of split-window or due to a different default behaviour by Emacs, invoking the split-window-below besides splitting the window, it switched the buffer in the non-focused window to the next buffer.

Currently (Emacs 24.x), the split-window and siblings split-window-below and split-window-right don't seem to allow such a customization. Is this true?

If so, how to tweak Emacs to have this behaviour? Redefining split-window or split-window-below and split-window-right to have an extra step of switching to the next on the non-focused window. This could be done with advices:

(defun split-window-and-next-buffer (new-window)
  (let ((old-window (selected-window)))
    (select-window new-window)
    (next-buffer)
    (select-window old-window)
    new-window))

(defadvice split-window-right (after split-window-right-and-next-buffer
                     activate protect compile)
  (split-window-and-next-buffer ad-return-value))

(defadvice split-window-below (after split-window-bellow-and-next-buffer
                      activate protect compile)
  (split-window-and-next-buffer ad-return-value))

With the corrections indicated by lawlist which are already available above the advices already work and I get the intended behaviour, but it isn't customizable to have the old behaviour.

Upvotes: 3

Views: 368

Answers (1)

lawlist
lawlist

Reputation: 13467

In response to the question, the original poster might want try changing the spelling of the word below within the code posted.


This function adds three lines of code (at the end) to the current version of Emacs Trunk split-window-below and renames the function to lawlist-split-window-below with a defalias. One closing parentheses was moved to the end of the function to permit using two of the let bindings defined farther up in the function. If the user wants focus in the new-window (after exiting the function) instead, then just remove the last line of code (select-window old-window).

(defun lawlist-split-window-below (&optional size)
  "Split the selected window into two windows, one above the other.
The selected window is above.  The newly split-off window is
below, and displays the 'next-buffer'.  Return the new window.

If optional argument SIZE is omitted or nil, both windows get the
same height, or close to it.  If SIZE is positive, the upper
\(selected) window gets SIZE lines.  If SIZE is negative, the
lower (new) window gets -SIZE lines.

If the variable `split-window-keep-point' is non-nil, both
windows get the same value of point as the selected window.
Otherwise, the window starts are chosen so as to minimize the
amount of redisplay; this is convenient on slow terminals."
  (interactive "P")
  (let ((old-window (selected-window))
    (old-point (window-point))
    (size (and size (prefix-numeric-value size)))
        moved-by-window-height moved new-window bottom)
    (when (and size (< size 0) (< (- size) window-min-height))
      ;; `split-window' would not signal an error here.
      (error "Size of new window too small"))
    (setq new-window (split-window nil size))
    (unless split-window-keep-point
      (with-current-buffer (window-buffer)
    ;; Use `save-excursion' around vertical movements below
    ;; (Bug#10971).  Note: When the selected window's buffer has a
    ;; header line, up to two lines of the buffer may not show up
    ;; in the resulting configuration.
    (save-excursion
      (goto-char (window-start))
      (setq moved (vertical-motion (window-height)))
      (set-window-start new-window (point))
      (when (> (point) (window-point new-window))
        (set-window-point new-window (point)))
      (when (= moved (window-height))
        (setq moved-by-window-height t)
        (vertical-motion -1))
      (setq bottom (point)))
    (and moved-by-window-height
         (<= bottom (point))
         (set-window-point old-window (1- bottom)))
    (and moved-by-window-height
         (<= (window-start new-window) old-point)
         (set-window-point new-window old-point)
         (select-window new-window)))
    ;; Always copy quit-restore parameter in interactive use.
    (let ((quit-restore (window-parameter old-window 'quit-restore)))
      (when quit-restore
    (set-window-parameter new-window 'quit-restore quit-restore)))
    new-window)
  (select-window new-window)
  (next-buffer)
  (select-window old-window)))

(defalias 'split-window-below 'lawlist-split-window-below)

Upvotes: 3

Related Questions