1

Typically I have two windows, left and right, with the left window (call it the "editing window") showing a buffer in a prog-mode or text-mode and the right window (call it the "auxiliary window") showing something else: documentation, Magit, make output, or just the start-up screen.

My font size and frame width are such that, if these windows' widths are balanced, the editing window is (by a small amount) not wide enough to show all its content out to its fill-column, while the auxiliary window has more width than it typically needs. I would like Emacs to keep the windows sized so that the editing window (or each window, for simplicity) has enough width to show its fill-column.

I have the following Elisp running in the prog-mode-hook and the text-mode-hook:

   (setq-local fit-window-to-buffer-horizontally t)
   (let (w (get-buffer-window))
     (fit-window-to-buffer w nil nil nil (+ fill-column 8))
     (window-preserve-size w t t)))

(The added 8 columns are to account for the fringes, line numbers, etc.)

If I start Emacs as emacs <FILE>, such that it opens with a left window showing FILE and a right window showing the start-up screen, the above code does make the left window larger, such that its fill-column is visible. However, if I then open Magit or a help window, or run make with Projectile, such that Magit or help or make takes over the right window, or even if I open another file with C-x C-f in the left window, the windows' widths become balanced, such that the left window may no longer be wide enough to show all of FILE (depending on its fill-column) and Magit or whatever has more width than it needs.

How can I make Emacs respect windows' buffers' fill-columns when resizing windows?

I have seen the window hooks, but those seemed promising only until I saw "Window change functions should not [...] change the [...] size [...] of any window".

I considered window-min-height and window-min-width, but they, as I understand it, apply only to all windows, which is unsatisfactory, as the width I want varies by buffer. I tried window-size-fixed, but, by fixing the height of the editing window, it prevented completions from appearing at the bottom of the frame.

4
  • You might try writing a custom function to assign to the split-window parameter for windows you wish to have special behaviour? You could then use a window change hook to add or remove that parameter, in accordance with the buffer it was currently displaying. (Suggestion is entirely untested by me.)
    – phils
    Commented Mar 19, 2022 at 2:51
  • I tried putting a function in that parameter to write a message into *Messages*, which shows that it doesn't get called when I (for example) open Magit, which is as I expected: I didn't think any window was getting split; rather, the existing left window gets repurposed for Magit/help/make.
    – user570286
    Commented Mar 19, 2022 at 3:27
  • 1
    The variables window-min-height and window-min-width can be helpful to control the minimum size vertically and horizontally. See also the variable window-size-fixed. The doc-strings describe how those variables may be used.
    – lawlist
    Commented Mar 19, 2022 at 6:18
  • window-size-fixed definitely looks useful here. Perhaps display-buffer-alist could be used to set the window width when displaying the buffer (see C-h i g (elisp)Buffer Display Action Alists) and window-size-fixed could prevent other things from changing it?
    – phils
    Commented Mar 19, 2022 at 9:39

1 Answer 1

1

On 2022-05-17, I found that my problem is solved by setting the window width from window-configuration-change-hook, by running this in prog-mode-hook and text-mode-hook:

   (setq-local fit-window-to-buffer-horizontally t)
   (add-hook
    'window-configuration-change-hook
    'user570286/set-window-width-per-content
    nil t)
   (user570286/set-window-width-per-content)

with this definition of user570286/set-window-width-per-content:

(defun user570286/set-window-width-per-content ()
  "[...]"
  (let (w (get-buffer-window))
    (fit-window-to-buffer w nil nil nil (+ fill-column 9))))

(with a different name than "user570286" in the original code).

This solution does prevent me from being able to change window widths manually, but I'm okay with that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.