(Re)generate: (find-multiwindow-intro)
Source code: (find-efunction 'find-multiwindow-intro)
More intros: (find-eev-quick-intro)
(find-eev-intro)
(find-eval-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
It is meant as both a tutorial and a sandbox.
1. Introduction
In many situations - for example, when we want to script a
debugger, or to test programs that have to talk to one another,
or to control several external machines simultaneously - the
default window setup for eepitch, which is this,
____________________
| | |
| | |
| script | shell |
| | |
| | |
|__________|_________|
is not enough; other setups, like these,
______________________
| | | _________________________
| | shell A | | | |
| |___________| | script | GDB |
| script | | | | |
| | shell B | |____________|____________|
| |___________| | | |
| | | | program | program |
| | shell C | | I/O | source |
|__________|___________| |____________|____________|
may be necessary. Eev comes with a few _low-level_ tools for
creating these setups; they are not very smart, but they should
be easy to understand and to tweak - and I have the impression
that ideas for good high-level tools will only come from
practical experimentation.
2. `find-wset'
Suppose that we are in a buffer A, and we want to create a window
configuration with A at the left, and with the buffers B and C
stacked on one another at the right. That is:
___________ ___________
| | | | |
| | | | B |
| A | --> | A |_____|
| | | | |
| | | | C |
|___________| |_____|_____|
To do that from the keyboard we could type this:
C-x 3 C-x o C-x b B RET C-x 2 C-x o C-x b C RET
You can try that here (the initial `C-x 1' is an extra, for
convenience):
(eek "C-x 1 ;; delete-other-windows
C-x 3 ;; split-window-horizontally (left/right)
C-x o ;; other-window (-> right)
C-x b B RET ;; switch to the buffer `B'
C-x 2 ;; split-window-vertically (upper/lower)
C-x o ;; other-window (-> lower right)
C-x b C RET ;; switch to the buffer `C'
")
We can write something equivalent to that as a `progn', in a way
that makes it easy to replace later the `C-x b B RET' and the
`C-x b C RET' by arbitrary sexp hyperlinks. We get:
(progn (eek "C-x 1 C-x 3 C-x o")
(find-ebuffer "B")
(eek "C-x 2 C-x o")
(find-ebuffer "C")
(eek "C-x o")
)
When I started to rewrite my window configurations into that form
I realized that the `eek's were being used in a very limited way
- they only invoked a very small repertoire of window commands,
all of them starting with `C-x'. So maybe I should have an
interpreter for a simple language of window commands and sexp
hyperlinks, in the which window setup above could be expressed
like this:
'("13o"
(find-ebuffer "B")
"2o"
(find-ebuffer "C")
"o"
)
`find-wset' supports something like that, but with all the window
command strings collapsed into a single one, with "_"s meaning
"execute the next sexp from the sexp list". The corresponding
call to `find-wset' is:
(find-wset "13o_2o_o" '(find-ebuffer "B") '(find-ebuffer "C"))
For the full list of supported window command characters - and
how to extend it - see the source:
(find-eev "eev-multiwindow.el")
3. High-level words
Very often we want to create window setups like
_______________ _______________
| | | | | |
| | | | | B |
| A | B | or | A |_______| ;
| | | | | |
| | | | | C |
|_______|_______| |_______|_______|
there are shorthands for that. If you run
(find-2a sexpA sexpB)
that will create a window setting like the one at the left above,
initially with two copies of the current buffer, then will run
sexpA at the window "A" and sexpB at the window "B", and
finally will select the window "A", i.e., leave the cursor at
the window at the left; this
(find-2b sexpA sexpB)
will do exactly the same as the `(find-2a ...)' above, but will
select the window "B" - the one at the right - at the end of
the process. For three-window settings we have these:
(find-3a sexpA sexpB sexpC)
(find-3b sexpA sexpB sexpC)
(find-3c sexpA sexpB sexpC)
all three create the three-window setting at the right above,
initially with all three windows displaying the current buffer,
then run sexpA at the window "A", sexpB at the window "B",
and sexpC at the window "C"; the difference is that find-3a
selects the window "A", find-3b the window "B", find-3c the
window "C".
4. Several eepitch targets
If we try to build a window setup like this one, with two eepitch
targets, with just `find-wset', we will run into problems -
________________________
| | |
| | *shell* |
| script |_____________|
| | |
| | *shell 2* |
|__________|_____________|
because `(eepitch-shell)' and `(eepitch-shell2)' try to create a
shell buffer and put it in an _another_ window, not the one we
are in... one solution is to call the `(eepitch-*)' sexps inside
an `ee-here', like this:
(ee-here '(eepitch-shell))
(ee-here '(eepitch-shell2))
where `ee-here' is a hack that runs a sexp in a way that
preserves the current window configuration, then switches the
buffer in the current selected window to the current eepitch
target. We can use this to create the window setting above,
(find-wset "13o2_o_o"
' (ee-here '(eepitch-shell))
' (ee-here '(eepitch-shell2))
)
This is too long - and would make a very bad one-liner - but
there are two shorthands. First, "e" is a variant of "_" that
runs its sexp inside an `(ee-here ...) - so this is equivalent
the thing above,
(find-wset "13o2eoeo"
'(eepitch-shell)
'(eepitch-shell2)
)
Second, these things are useful enough to deserve a high-level
word, so this is equivalent to:
(find-3ee '(eepitch-shell) '(eepitch-shell2))
5. Restarting eepitch targets
Sometimes we want to do the same as above, but restarting both
eepitch targets, i.e., something like this:
(find-3ee '(progn (eepitch-shell) (eepitch-kill) (eepitch-shell))
'(progn (eepitch-shell2) (eepitch-kill) (eepitch-shell2))
)
There's a variant of `ee-here' that does that: `ee-here-reset'.
For example,
(ee-here-reset '(eepitch-shell2))
is equivalent to:
(ee-here '(progn (eepitch-shell2) (eepitch-kill) (eepitch-shell2)))
and the letter "E" is a variant of "e" that uses
`ee-here-reset' instead of `ee-here'; also, `find-3EE' is a
variant of `find-3ee' that restarts both targets. Let's adapt
this example,
(find-eepitch-intro "3. Other targets")
to make it show the two eepitch targets at once in a three-window
settings. It becomes:
* (find-3EE '(eepitch-shell) '(eepitch-python))
* (eepitch-shell)
echo Hello... > /tmp/o
* (eepitch-python)
print(open("/tmp/o").read())
* (eepitch-shell)
echo ...and bye >> /tmp/o
* (eepitch-python)
print(open("/tmp/o").read())
** Now compare:
* (eek "C-x 1")
* (find-3ee '(eepitch-shell) '(eepitch-python))
* (find-3EE '(eepitch-shell) '(eepitch-python))
6. Non-trivial examples
See:
(find-eev-quick-intro "6.2. Other targets")
(find-eev-quick-intro "6.2. Other targets" "(find-3EE")
(find-rcirc-intro "1. The example that I use in workshops")
(find-prepared-intro "3. An `ee' for Python")
(find-prepared-intro "4. `eepy'")
The examples with `find-3EE' were created using `M-#', as
explained in the next section.
7. Eepitch blocks for two targets
An eepitch script with two targets uses several different kinds
of red star lines - `(eepitch-target1)', `(eepitch-target2)',
`(find-3EE ...)', `(find-3ee ...)', etc. We don't want to have to
type all those by hand, so there is a hack similar to `M-T' that
generates all those kinds from just "target1" and "target2"
to let us just copy around the sexps we need.
This key binding for this hack is `meta-shift-3' - that Emacs
sees as `M-#' - but it is disabled by default. To enable it, do
this:
;; See: (find-eevfile "eev-mode.el" "eewrap-two-eepitches")
(define-key eev-mode-map "\M-#" 'eewrap-two-eepitches)
Now compare the result of typing `M-T' here,
python
with the result of typing `M-#' on this line,
shell python
which yield this:
* (find-3EE '(eepitch-shell) '(eepitch-python))
* (find-3ee '(eepitch-shell) '(eepitch-python))
* (eepitch-shell)
* (eepitch-python)
Remember that The line with `find-3EE' restart the two targets,
and the line with `find-3ee' just recreates the window setting
with the two targets but without restarting them; so the line
with `find-3EE' sort of works as two `eepitch-kill's.
8. Adding support for new characters in `find-wset'
The standard characters supported by `find-wset' are these:
char action key
---- ---------------------------- ---------
`1' `delete-other-windows' (C-x C-1)
`2' `split-window-vertically' (C-x C-2)
`3' `split-window-horizontally' (C-x C-3)
`s' `split-window-sensibly'
`o' `other-window' (C-x o)
`+' `balance-windows' (C-x +)
`_' execute the next sexp
but the action of each one is defined in a different function,
and to add support for a new character, say, `=', we just need to
define a function with the right name - in this case,
`find-wset-='.
The source code is simple enough, so take a look:
(find-eev "eev-multiwindow.el" "find-wset-_")