emacs-devel
[Top][All Lists]
Advanced

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

Some question about display-buffer action functions


From: Juanma Barranquero
Subject: Some question about display-buffer action functions
Date: Sun, 29 Jan 2012 03:44:40 +0100

A long and boring and two just boring questions regarding the new
window machinery for display-buffer.


1)  [tl;dr: perhaps some sort of display-buffer hook (or hook actions)
would make action functions more flexible.]

I'm converting window-related functions from my .emacs to use
display-buffer's "action functions" (AF from now on), with the goal of
getting rid of as much custom code as possible, or at least converting
my custom ad hoc functions into more generic custom AFs. Ideally, the
AFs should be generic enough to be worthy candidates for inclusion in
future releases (for example,
display-buffer-choose-window-with-predicate).

A repeated problem I find is what to do when windows need to be set up
in some specific way; for example, to make them dedicated, or to add
my own window parameters.

[In the following example, I'm not claiming my setup is generally
useful to anyone else; I'm talking only about the "window setup"
problem.]

In most cases, I use a single-window configuration, except when I'm
developing code in a mode with an inferior process (sql, lisp, scheme,
python, and I also use ielm as "inferior mode" of elisp buffers). In
these cases, I split the frame in two windows, with the one above
(SUP) showing the code, and the one below (INF) showing the inferior
process. INF has a specific height, a window parameter that says that
it is to be used only for inferior processes, and it is strongly
dedicated, to prevent bs-cycle-*, which use "(switch-to-buffer next
nil t)", to switch buffers by accident.

Suppose I have a Python buffer in SUP, and no INF. Starting the
inferior process should create INF, and display *Python*. Now, in SUP
I switch to an SQL-mode buffer (INF is not affected). Starting the
MySQL inferior process generates and displays the *SQL* buffer, which
must appear in INF.

I have a custom AF called jb-inferior, and a function jb-setup which
sets up the window to my liking.

It seems straightforward to use display-buffer-alist for that, so I
add "*SQL*" and "*Python*" to that variable, with an AF of
jb-inferior.

Now, in an ideal world, after calling (pop-to-buffer BUFFER) for one
of these buffers, the process would be:

 - jb-inferior is called, looks for INF; if found and alive, use it,
and return INF; else return nil.
 - If nil, another, non-custom AF (likely
display-buffer-pop-up-window) will take care of selecting/creating the
appropriate window and returning it.
 - Then, call jb-setup for the window selected.

which is quite modular and elegant. But there's no way to call
jb-setup after selecting the window, at least not easily. I can think
of a few answers, but they start ugly and go down from there:

- Invoke pop-to-buffer (or display-buffer) from inside a custom
function, like this:

  (defun my-create-inferior-buffer-and-window (my-buffer)
    (pop-to-buffer my-buffer)
    (jb-setup (get-buffer-window my-buffer)))

 which will work in this particular case, but it's not a generic
answer in cases where display-buffer and friends are called from code
not under my control.

- Modify jb-inferior to always return a window, either finding INF or
spliting SUP, so it can run jb-setup before returning INF. This works
and it's easy, but it just kills modularity and elegance, and forces
jb-inferior to do a poor job of duplicating the work of the standard
AFs.

- Use window hooks (window-scroll-functions,
window-size-change-functions or window-configuration-change-hook),
which is not nice because the correspondence buffer<->window, known
while running display-buffer, is lost and has to be recomputed; and
additionally, these hooks run for every window created or buffer
displayed, which is wasted work.

- Or use a custom split-window-preferred-function. Most horrible
because it would destroy abstraction.

One possible answer would be having a
display-buffer-(after-)functions, which would get passed the buffer
and window after the window has been selected. (A -before-hook seems
less useful, and can be simulated with an AF which runs the code
you're interested and always return nil). Another one would be to have
a hook entry for the action alist (after-selecting-window-function or
somesuch) that would be run by the (custom and non-custom) AFs as the
last thing done upon selecting a window, just before returning it.


2)  Is there any way to set up the quit-window parameter of a window
so quit-window just always deletes the window? In the case above, when
I'm in INF and type quit-window I always want to destroy the window.
Even if INF was assigned to *Python* and then *SQL*, quit-window
should not go back to *Python*. Currently I'm forced to do

(defun jb-bury-interact (&optional finish)
  "Bury inferior interactive buffer.
If FINISH, terminate inferior process."
  (interactive "P")
  (unless (one-window-p t)
    (when finish (comint-send-eof))
    (bury-buffer)
    (window--delete nil t)))


3) It would be nice to make writing custom AFs simpler. Currently I'm
just ignoring the inhibit-same-window and reusable-frames actions in
my AFs (not to mention display-buffer-reuse-frames and pop-up-frames)
because it is a PITA to wrap your head around them...


    Juanma



reply via email to

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