(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 a2. `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)