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.

user570286
  • 121
  • 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 Mar 19 '22 at 02: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 Mar 19 '22 at 03: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 Mar 19 '22 at 06: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 Mar 19 '22 at 09:39

1 Answers1

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.

user570286
  • 121
  • 4