(Re)generate: (find-prepared-intro)
Source code: (find-eev "eev-intro.el" "find-prepared-intro")
More intros: (find-eev-quick-intro)
(find-eev-intro)
(find-eepitch-intro)
This buffer is _temporary_ and _editable_.
It is meant as both a tutorial and a sandbox.
In my presentation at the EmacsConf2019
I mentioned very briefly in this slide -
http://anggtwu.net/LATEX/2019emacsconf.pdf#page=4
that `M-x eev' was a "very primitive way to send the region to a
shell". This intro gives a few more details about that, but it
is very incomplete...
1. Prepared shells
Long before eepitch had been created, eev had another way -
technically much simpler, but clumsier from the user's point of
view - to send commands to external shells (and other shell-like
programs; but to simplify we will say just "shells"). Here is
an overview of how it worked: if the user marked the three lines
below,
rm -Rfv /tmp/foo/
mkdir /tmp/foo/
cd /tmp/foo/
and typed `M-x eev' (which stood for "Emacs-execute-verbosely")
then Emacs would save those three lines into a temporary script
file, usually "~/.eev/ee.sh"; that would be just half of
"sending commands to an external shell", and for the other half
the user would have to go to an external prepared shell - that
would usually be running in an xterm, and totally independent
from Emacs - and type "ee" there. The shell had to be
"prepared" in the sense that it would understand the "ee"
command correctly, as meaning: "execute the commands in the
temporary script as if the user were typing them at the prompt".
Technically, that would mean that instead of calling
"~/.eev/ee.sh" as a shell script its contents would be
"sourced" - i.e., executed in the current shell context - and
in verbose mode.
Usually we would prepare bash by patching the file ~/.bashrc and
putting the definition for "ee" there. We will discuss how to
do that later; now let's test a simple environment in which `M-x
eev' and "ee" work. First execute these two sexps:
(make-directory "~/.eev/" 'force)
(eev "rm -Rv /tmp/foo\nmkdir /tmp/foo/\ncd /tmp/foo/\n")
Now run this script:
* (eepitch-bash)
* (eepitch-kill)
* (eepitch-bash)
export PS1='$PWD# '
function ee () { set -v; . ~/.eev/ee.sh; set +v; }
ee
The `ee' will execute the rm/mkdir/cd in a
2. `ee'
[TODO: Write this section! Explain how several interpreters can
be programmed to accept an `ee' command to execute temporary
scripts...]
See (obs: this is very old!):
http://anggtwu.net/eev-article.html#making-progs-receive-cmds
(find-eev "eev-langs.el")
(find-eev "eev-bounded.el")
(find-eev "eev-rctool")
3. An `ee' for Python
Here is a simple way to make Python execute commands saved in a
temporary script when the user types `ee()' (note that it is not
just `ee' - the `()' is needed). We will show first an example in
which the temporary script is prepared by running "cat" from a
shell - then we will explain a more user-friendly way to save a
region from the current buffer as the temporary script.
Note that the demo below uses `find-wset', which is an
advanced (i.e., hackish) feature explained here:
(find-multiwindow-intro "Several eepitch targets")
* (find-3EE '(eepitch-shell) '(eepitch-python))
* (find-3ee '(eepitch-shell) '(eepitch-python))
* (eepitch-python)
import os
def ee():
exec(open(os.getenv("HOME")+"/.eev/ee.py").read(), globals())
* (eepitch-shell)
cat > ~/.eev/ee.py <<'%%%'
print(1+2)
%%%
* (eepitch-python)
ee()
* (eepitch-shell)
cat > ~/.eev/ee.py <<'%%%'
def foo (x):
return x*x
print(foo(5))
%%%
* (eepitch-python)
ee()
print(foo(6))
4. `eepy'
The function `eev' receives three parameters, called `s', `e', and
`altfile'; `e' and `altfile' are optional, and `s' should be either a
string or a number. When `s' is a string, then the commands to be
saved into the temporary script are taken from `s'; the numeric case
will be discussed later.
A call to
(eev "print(1+2)" nil "~/.eev/ee.py")
writes "print(1+2)" (with an added trailing newline, but that's
a technical detail) into the "alternative file"
"~/.eev/ee.py" - the default would be "~/.eev/ee.sh". We can
use that to simplify our demo a bit:
* (eek "C-x 1")
* (eepitch-python)
* (eepitch-kill)
* (eepitch-python)
import os
def ee():
exec(open(os.getenv("HOME")+"/.eev/ee.py").read(), globals())
* (eev "print(1+2)" nil "~/.eev/ee.py")
ee()
* (eev "def foo (x):\n return x*x\n\nprint(foo(5))" nil "~/.eev/ee.py")
ee()
print(foo(6))
In the example below the first line defines a `eepy' in a
simplistic way:
* (defun eepy (s &optional e) (eev s e "~/.eev/ee.py"))
* (eek "C-x 1")
* (eepitch-python)
* (eepitch-kill)
* (eepitch-python)
import os
def ee():
exec(open(os.getenv("HOME")+"/.eev/ee.py").read(), globals())
* (eepy "print(1+2)")
ee()
* (eepy "def foo (x):\n return x*x\n\nprint(foo(5))")
ee()
print(foo(6))
5. `M-x eepy' and `M-x eev'
Now let's define a more realistic `eepy' - one that can also be
called interactively. We want `M-x eepy' to save the current
_region_ into the temporary script; `eepy' has to be a _command_,
and we will use the argument "r" to its `interactive' clause,
to make the function `eepy' receive two numbers - the start and
the end of the region - and it will pass these two numbers to
`eev'.
(defun eepy (s &optional e)
"Save the region between S and E (or the string S) into ~/.eev/ee.py ."
(interactive "r")
(eev s e "~/.eev/ee.py"))
When the first argument, `s', to `eev', is a number, not a
string, then `eev' expects the second argument, `e', to also be a
number - and then `s' and `e' are considered as the extremities
of a region of text in the current buffer. This idea - that the
first argument can be either a string or a number - comes from:
(find-efunctiondescr 'write-region "If START is a string")
But try these:
(ee-se-to-string "foo" nil)
(ee-se-to-string-with-nl "foo" nil)
(ee-se-to-string "foo\n" nil)
(ee-se-to-string-with-nl "foo\n" nil)
(ee-se-to-string (- (point) 5) (point))
(ee-se-to-string-with-nl (- (point) 5) (point))
(ee-se-to-string (point) (- (point) 5))
(ee-se-to-string-with-nl (point) (- (point) 5))
[Garbage:]
(find-elnode "Defining Commands")
(find-defun-intro "\ninteractive\n")
(find-efunction 'eev)