From: Joost Kremers <joostkremers@fastmail.fm>
To: emacs-devel <emacs-devel@gnu.org>
Subject: Better handling of window margins
Date: Tue, 01 Dec 2015 22:28:44 +0100 [thread overview]
Message-ID: <87mvttsvsj.fsf@fastmail.fm> (raw)
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
next reply other threads:[~2015-12-01 21:28 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-01 21:28 Joost Kremers [this message]
2015-12-02 8:23 ` Better handling of window margins martin rudalics
2015-12-02 13:41 ` Eli Zaretskii
2015-12-02 17:43 ` martin rudalics
2015-12-02 17:53 ` Eli Zaretskii
2015-12-02 18:11 ` martin rudalics
2015-12-03 6:49 ` Eli Zaretskii
2015-12-03 18:16 ` martin rudalics
2015-12-03 20:09 ` Eli Zaretskii
2015-12-03 20:43 ` Stefan Monnier
2015-12-04 8:14 ` Eli Zaretskii
2015-12-04 13:22 ` Stefan Monnier
2015-12-04 14:46 ` Eli Zaretskii
2015-12-04 17:30 ` Stefan Monnier
2015-12-04 18:45 ` Eli Zaretskii
2015-12-04 20:55 ` Stefan Monnier
2015-12-04 21:13 ` Eli Zaretskii
2015-12-04 21:33 ` Stefan Monnier
2015-12-05 7:56 ` Eli Zaretskii
2015-12-05 15:17 ` Stefan Monnier
2015-12-05 15:49 ` Eli Zaretskii
2015-12-06 4:27 ` Stefan Monnier
2015-12-06 5:02 ` John Wiegley
2015-12-06 16:10 ` Eli Zaretskii
2015-12-06 20:24 ` Yuri Khan
2015-12-07 3:32 ` Eli Zaretskii
2015-12-07 10:35 ` Yuri Khan
2015-12-07 16:39 ` Eli Zaretskii
2015-12-07 0:29 ` John Wiegley
2015-12-07 16:24 ` Eli Zaretskii
2015-12-07 17:35 ` John Wiegley
2015-12-07 17:38 ` Achim Gratz
2015-12-07 17:41 ` John Wiegley
2015-12-07 17:50 ` Achim Gratz
2015-12-07 17:36 ` Stefan Monnier
2015-12-07 17:39 ` John Wiegley
2015-12-07 18:42 ` Stefan Monnier
2015-12-07 19:14 ` John Wiegley
2015-12-04 8:07 ` martin rudalics
2015-12-04 9:42 ` Eli Zaretskii
2015-12-04 10:21 ` martin rudalics
2015-12-04 15:34 ` Eli Zaretskii
2015-12-04 16:56 ` martin rudalics
2015-12-04 18:34 ` Eli Zaretskii
2015-12-04 19:23 ` martin rudalics
2015-12-02 19:52 ` Joost Kremers
2015-12-03 7:17 ` Eli Zaretskii
2015-12-02 19:55 ` Joost Kremers
2015-12-03 7:21 ` Eli Zaretskii
2015-12-04 12:49 ` John Wiegley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87mvttsvsj.fsf@fastmail.fm \
--to=joostkremers@fastmail.fm \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.