emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Better handling of window margins


From: Joost Kremers
Subject: Better handling of window margins
Date: Tue, 01 Dec 2015 22:28:44 +0100
User-agent: mu4e 0.9.15; emacs 24.5.2

In two recent threads, one here ("Window splitting issues with margins")
and one on bugs.gnu.emacs (bug 22009), some issues were discussed with
window margins that could stand improvement. Two issues specifically
came up:

1) If two modes use the margins at the same time, there is no way to
ensure that they don't interfere. Specifically, if package A sets the
(left) margin to a value x and package B sets it to a value y, whichever
mode sets the margin last will win out. Which of the two packages this
is depends on the order in which they were activated and on the hooks
that the modes use to adjust the margins. There is currently no good way
for a mode to prevent such interference reliably.

2) When a window's width is changed, Emacs currently assumes that the
margins need to be retained, i.e., their width doesn't change. This in
itself is not a problem, because a mode that does want to change the
margin width can do so in `window-configuration-change-hook'. However,
it becomes a problem in `window-splittable-p' (and
'split-window-sensibly'), because this function makes this same
assumption when determining whether a window can be split horizontally.
The assumption is not necessarily correct, specifically in modes such as
`writeroom-mode', `olivetti' (both on MELPA) or `darkroom-mode' (on
ELPA), that use the margins to center the text area in the window. In
such modes, the width of the margins is determined on the basis of the
desired text width and the current window width. When the window width
changes, the margins are recalculated. `window-splittable-p' currently
determines that such windows cannot be split horizontally, even when the
window (including margins) is wide enough. (It's just the text area that
isn't, but the aforementioned modes compensate for this by adjusting the
margins after the window has been split.)

I'd like to outline a way to hopefully solve both issues. The basic idea
of the proposal is that `set-window-margins' keeps track of which modes
set the margins and to which values they set them and whether they are
static (i.e., should not be changed when the window width changes) or
dynamic (can be changed). In detail:

* Add a window parameter (say `window-margins-alist') that records
  margin settings from different modes. E.g.:

  ((nlinum 4 0) (git-gutter 2 0))

* Amend `set-window-margins' to take two additional parameters:

  (set-window-margins WINDOW LEFT-WIDTH &optional RIGHT-WIDTH SYM DYNAMIC)

  SYM is a symbol (chosen by the caller) that identifies the mode that
  is setting the margins.

* If `set-window-margins' is called with a non-nil value for SYM, an
  entry is recorded in `window-margins-alist', or updated if one is
  already present, or deleted if both LEFT-WIDTH and RIGHT-WIDTH are
  nil. Subsequently, the window margins are set to the total of all
  requested widths, so in the example above to (6 0).

* If `set-window-margins' is called without SYM, it sets the margins
  without checking `window-margins-alist', i.e., it behaves as it does
  now, in order to prevent existing code from breaking.

* If DYNAMIC is t, this is recorded in `window-margins-alist', e.g.:

  ((nlinum 4 0) (git-gutter 2 0) (writeroom 40 40 t))  

  In this case, the window width is set to the *largest* dynamic value,
  or to the *total* of all static values, whichever is larger. So in the
  present example, `set-window-margins' should compare 4+2=6 with 40 for
  the left margin and 0+0=0 with 40 for the right margin and
  consequently set the margins to (40 40).

* `window-splittable-p' can check the contents of `window-margins-alist'
  and use the info to determine whether a window can be split
  horizontally: dynamic margins can be adjusted, so the horizontal
  splittability should be determined on the basis of text width plus
  dynamic margins minus static margins. In the present example:

  (+ (- 40 4 2) (- 40 0 0) (window-text-width))

  This value would be used instead of (window-width) in the current
  implementation of `window-splittable-p'.

* If the value of `window-margin-alist' is nil, but the margins are
  non-nil, `window-splittable-p' should behave as it does now.

* Obviously, `window-splittable-p' (or any function that calls it)
  should not update the margins itself. That is up to the modes that use
  the margins, using `window-configuration-change-hook'.

* A mode that wants to display something in the margin can check the
  value of `window-margins-alist' to see whether another mode is using
  the margins and can adjust its behaviour accordingly, e.g., by
  prepending a space to the string it displays, so that it is visually
  separate from whatever else is displayed in the margin.

I guess that's it. Comments & suggestions welcome.

[PS: I'm not really familiar with Emacs sources, so I may be overlooking
important things. Also, I can handle myself in Elisp, but I'm not much
of a C programmer, and `set-window-margins' is a C function. I'd be
willing to dive into the sources to try and come up with a patch, but it
would take its time and I'd probably need some hand-holding... If
someone else wants to do it, that would be fine with me.]


-- 
Joost Kremers
Life has its moments



reply via email to

[Prev in Thread] Current Thread [Next in Thread]